|
|
@ -0,0 +1,65 @@
|
|||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
.DS_Store
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata/
|
||||
|
||||
## Other
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
*.xcscmblueprint
|
||||
|
||||
## Obj-C/Swift specific
|
||||
*.hmap
|
||||
*.ipa
|
||||
|
||||
## Playgrounds
|
||||
timeline.xctimeline
|
||||
playground.xcworkspace
|
||||
|
||||
# Swift Package Manager
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
|
||||
# Packages/
|
||||
.build/
|
||||
|
||||
# CocoaPods
|
||||
#
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||
#
|
||||
# Pods/
|
||||
|
||||
# Carthage
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||
# Carthage/Checkouts
|
||||
|
||||
Carthage/Build
|
||||
|
||||
# fastlane
|
||||
#
|
||||
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||
# screenshots whenever they are needed.
|
||||
# For more information about the recommended setup visit:
|
||||
# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
|
||||
|
||||
fastlane/report.xml
|
||||
fastlane/screenshots
|
||||
|
|
@ -0,0 +1,736 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
F202573A1C7343D20069B33A /* ImageName.swift in Sources */ = {isa = PBXBuildFile; fileRef = F20257391C7343D20069B33A /* ImageName.swift */; };
|
||||
F202573C1C7418920069B33A /* PickedAssetList.swift in Sources */ = {isa = PBXBuildFile; fileRef = F202573B1C7418920069B33A /* PickedAssetList.swift */; };
|
||||
F2131F431C79615700797887 /* SwipeInteractionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2131F421C79615700797887 /* SwipeInteractionController.swift */; };
|
||||
F218D7D61C6B3D22001FCED1 /* PhotoKitAlbumList.swift in Sources */ = {isa = PBXBuildFile; fileRef = F218D7D51C6B3D22001FCED1 /* PhotoKitAlbumList.swift */; };
|
||||
F218D7DE1C6C3A5B001FCED1 /* AlbumCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F218D7DD1C6C3A5B001FCED1 /* AlbumCell.swift */; };
|
||||
F23554261C69D19C00796DCA /* NohanaImagePicker.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F23554251C69D19C00796DCA /* NohanaImagePicker.storyboard */; };
|
||||
F23554281C69D5DB00796DCA /* NohanaImagePickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F23554271C69D5DB00796DCA /* NohanaImagePickerController.swift */; };
|
||||
F237249B1C6DCF96005D1E8A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F237249A1C6DCF96005D1E8A /* Images.xcassets */; };
|
||||
F23CC89E1CB745C800BCE443 /* ActivityIndicatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F23CC89D1CB745C800BCE443 /* ActivityIndicatable.swift */; };
|
||||
F24EB6901C68AEED0002EC86 /* AlbumListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F24EB68F1C68AEED0002EC86 /* AlbumListViewController.swift */; };
|
||||
F24EB6911C68AFB40002EC86 /* NohanaImagePicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F2C08D741C68651900B00181 /* NohanaImagePicker.framework */; };
|
||||
F24EB6921C68AFB40002EC86 /* NohanaImagePicker.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F2C08D741C68651900B00181 /* NohanaImagePicker.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
F25C10C21C8ED9BF007453C3 /* MomentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F25C10C11C8ED9BF007453C3 /* MomentViewController.swift */; };
|
||||
F25C69881CA23A0A005935D6 /* MomentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F25C69871CA23A0A005935D6 /* MomentCell.swift */; };
|
||||
F25C69901CA27311005935D6 /* EmptyIndicatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F25C698F1CA27311005935D6 /* EmptyIndicatable.swift */; };
|
||||
F25C69921CA28728005935D6 /* AlbumListEmptyIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F25C69911CA28728005935D6 /* AlbumListEmptyIndicator.swift */; };
|
||||
F25C699B1CA2B79A005935D6 /* ColorConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = F25C699A1CA2B79A005935D6 /* ColorConfig.swift */; };
|
||||
F26775DE1C701FA7002E786C /* ItemListType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F26775DD1C701FA7002E786C /* ItemListType.swift */; };
|
||||
F26775E11C7046C7002E786C /* ExpandingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F26775E01C7046C7002E786C /* ExpandingAnimationController.swift */; };
|
||||
F26775E51C70574F002E786C /* AnimatableNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F26775E41C70574F002E786C /* AnimatableNavigationController.swift */; };
|
||||
F26775E81C7073CD002E786C /* Size.swift in Sources */ = {isa = PBXBuildFile; fileRef = F26775E71C7073CD002E786C /* Size.swift */; };
|
||||
F26775EA1C71645A002E786C /* ContractingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F26775E91C71645A002E786C /* ContractingAnimationController.swift */; };
|
||||
F27029CB1C71C43A001647AB /* NohanaImagePicker.strings in Resources */ = {isa = PBXBuildFile; fileRef = F27029CD1C71C43A001647AB /* NohanaImagePicker.strings */; };
|
||||
F28F4AC31C6C49EE00B7D725 /* PhotoKitAssetList.swift in Sources */ = {isa = PBXBuildFile; fileRef = F28F4AC21C6C49EE00B7D725 /* PhotoKitAssetList.swift */; };
|
||||
F28F4AC51C6C59A500B7D725 /* PhotoKitAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = F28F4AC41C6C59A500B7D725 /* PhotoKitAsset.swift */; };
|
||||
F2C08D781C68651900B00181 /* NohanaImagePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = F2C08D771C68651900B00181 /* NohanaImagePicker.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
F2C08D951C688FC400B00181 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2C08D941C688FC400B00181 /* AppDelegate.swift */; };
|
||||
F2C08D971C688FC400B00181 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2C08D961C688FC400B00181 /* ViewController.swift */; };
|
||||
F2C08D9A1C688FC400B00181 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F2C08D981C688FC400B00181 /* Main.storyboard */; };
|
||||
F2C08D9C1C688FC400B00181 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F2C08D9B1C688FC400B00181 /* Assets.xcassets */; };
|
||||
F2C08D9F1C688FC400B00181 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F2C08D9D1C688FC400B00181 /* LaunchScreen.storyboard */; };
|
||||
F2C08DAA1C688FC400B00181 /* NohanaImagePickerSampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2C08DA91C688FC400B00181 /* NohanaImagePickerSampleTests.swift */; };
|
||||
F2DA29771C7749D600B0A8E3 /* NotificationInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2DA29761C7749D600B0A8E3 /* NotificationInfo.swift */; };
|
||||
F2DF3B151C6C76E500C1C0E4 /* AssetListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2DF3B141C6C76E500C1C0E4 /* AssetListViewController.swift */; };
|
||||
F2DF3B171C6C868E00C1C0E4 /* AssetCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2DF3B161C6C868E00C1C0E4 /* AssetCell.swift */; };
|
||||
F2DF3B2B1C6CC4DB00C1C0E4 /* AssetDetailListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2DF3B2A1C6CC4DB00C1C0E4 /* AssetDetailListViewController.swift */; };
|
||||
F2DF3B2D1C6D780100C1C0E4 /* AssetDetailCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2DF3B2C1C6D780100C1C0E4 /* AssetDetailCell.swift */; };
|
||||
F2FE1F781C901D9400FDBE7B /* MomentSectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2FE1F761C901D9400FDBE7B /* MomentSectionHeaderView.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
F24EB6931C68AFB40002EC86 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = F2C08D6B1C68651900B00181 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = F2C08D731C68651900B00181;
|
||||
remoteInfo = NohanaImagePicker;
|
||||
};
|
||||
F2C08DA61C688FC400B00181 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = F2C08D6B1C68651900B00181 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = F2C08D911C688FC400B00181;
|
||||
remoteInfo = NohanaImagePickerSample;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
F24EB6951C68AFB40002EC86 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
F24EB6921C68AFB40002EC86 /* NohanaImagePicker.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
F20257391C7343D20069B33A /* ImageName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageName.swift; sourceTree = "<group>"; };
|
||||
F202573B1C7418920069B33A /* PickedAssetList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PickedAssetList.swift; sourceTree = "<group>"; };
|
||||
F2131F421C79615700797887 /* SwipeInteractionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwipeInteractionController.swift; sourceTree = "<group>"; };
|
||||
F218D7D51C6B3D22001FCED1 /* PhotoKitAlbumList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoKitAlbumList.swift; sourceTree = "<group>"; };
|
||||
F218D7DD1C6C3A5B001FCED1 /* AlbumCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlbumCell.swift; sourceTree = "<group>"; };
|
||||
F23554251C69D19C00796DCA /* NohanaImagePicker.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NohanaImagePicker.storyboard; sourceTree = "<group>"; };
|
||||
F23554271C69D5DB00796DCA /* NohanaImagePickerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NohanaImagePickerController.swift; sourceTree = "<group>"; };
|
||||
F237249A1C6DCF96005D1E8A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
F23CC89D1CB745C800BCE443 /* ActivityIndicatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityIndicatable.swift; sourceTree = "<group>"; };
|
||||
F24EB68F1C68AEED0002EC86 /* AlbumListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlbumListViewController.swift; sourceTree = "<group>"; };
|
||||
F25C10C11C8ED9BF007453C3 /* MomentViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MomentViewController.swift; sourceTree = "<group>"; };
|
||||
F25C69871CA23A0A005935D6 /* MomentCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MomentCell.swift; sourceTree = "<group>"; };
|
||||
F25C698F1CA27311005935D6 /* EmptyIndicatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyIndicatable.swift; sourceTree = "<group>"; };
|
||||
F25C69911CA28728005935D6 /* AlbumListEmptyIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlbumListEmptyIndicator.swift; sourceTree = "<group>"; };
|
||||
F25C699A1CA2B79A005935D6 /* ColorConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorConfig.swift; sourceTree = "<group>"; };
|
||||
F26775DD1C701FA7002E786C /* ItemListType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ItemListType.swift; sourceTree = "<group>"; };
|
||||
F26775E01C7046C7002E786C /* ExpandingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpandingAnimationController.swift; sourceTree = "<group>"; };
|
||||
F26775E41C70574F002E786C /* AnimatableNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimatableNavigationController.swift; sourceTree = "<group>"; };
|
||||
F26775E71C7073CD002E786C /* Size.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Size.swift; sourceTree = "<group>"; };
|
||||
F26775E91C71645A002E786C /* ContractingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContractingAnimationController.swift; sourceTree = "<group>"; };
|
||||
F27029CC1C71C43A001647AB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/NohanaImagePicker.strings; sourceTree = "<group>"; };
|
||||
F27029CF1C71C4FE001647AB /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/NohanaImagePicker.strings; sourceTree = "<group>"; };
|
||||
F28F4AC21C6C49EE00B7D725 /* PhotoKitAssetList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoKitAssetList.swift; sourceTree = "<group>"; };
|
||||
F28F4AC41C6C59A500B7D725 /* PhotoKitAsset.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoKitAsset.swift; sourceTree = "<group>"; };
|
||||
F2C08D741C68651900B00181 /* NohanaImagePicker.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NohanaImagePicker.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F2C08D771C68651900B00181 /* NohanaImagePicker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NohanaImagePicker.h; sourceTree = "<group>"; };
|
||||
F2C08D791C68651900B00181 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
F2C08D921C688FC400B00181 /* NohanaImagePickerSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NohanaImagePickerSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F2C08D941C688FC400B00181 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
F2C08D961C688FC400B00181 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
F2C08D991C688FC400B00181 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
F2C08D9B1C688FC400B00181 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
F2C08D9E1C688FC400B00181 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
F2C08DA01C688FC400B00181 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
F2C08DA51C688FC400B00181 /* NohanaImagePickerSampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NohanaImagePickerSampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F2C08DA91C688FC400B00181 /* NohanaImagePickerSampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NohanaImagePickerSampleTests.swift; sourceTree = "<group>"; };
|
||||
F2C08DAB1C688FC400B00181 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
F2DA29761C7749D600B0A8E3 /* NotificationInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationInfo.swift; sourceTree = "<group>"; };
|
||||
F2DF3B141C6C76E500C1C0E4 /* AssetListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetListViewController.swift; sourceTree = "<group>"; };
|
||||
F2DF3B161C6C868E00C1C0E4 /* AssetCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetCell.swift; sourceTree = "<group>"; };
|
||||
F2DF3B2A1C6CC4DB00C1C0E4 /* AssetDetailListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetDetailListViewController.swift; sourceTree = "<group>"; };
|
||||
F2DF3B2C1C6D780100C1C0E4 /* AssetDetailCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetDetailCell.swift; sourceTree = "<group>"; };
|
||||
F2FE1F761C901D9400FDBE7B /* MomentSectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MomentSectionHeaderView.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
F2C08D701C68651900B00181 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F2C08D8F1C688FC400B00181 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F24EB6911C68AFB40002EC86 /* NohanaImagePicker.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F2C08DA21C688FC400B00181 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
F218D7DC1C6C3A3E001FCED1 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F218D7DD1C6C3A5B001FCED1 /* AlbumCell.swift */,
|
||||
F2DF3B161C6C868E00C1C0E4 /* AssetCell.swift */,
|
||||
F2DF3B2C1C6D780100C1C0E4 /* AssetDetailCell.swift */,
|
||||
F25C69871CA23A0A005935D6 /* MomentCell.swift */,
|
||||
F2FE1F761C901D9400FDBE7B /* MomentSectionHeaderView.swift */,
|
||||
F25C69911CA28728005935D6 /* AlbumListEmptyIndicator.swift */,
|
||||
);
|
||||
name = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F235541F1C698BE900796DCA /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F23554251C69D19C00796DCA /* NohanaImagePicker.storyboard */,
|
||||
F27029CD1C71C43A001647AB /* NohanaImagePicker.strings */,
|
||||
F237249A1C6DCF96005D1E8A /* Images.xcassets */,
|
||||
);
|
||||
name = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F23554291C69F38900796DCA /* Photos */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F218D7D51C6B3D22001FCED1 /* PhotoKitAlbumList.swift */,
|
||||
F28F4AC21C6C49EE00B7D725 /* PhotoKitAssetList.swift */,
|
||||
F28F4AC41C6C59A500B7D725 /* PhotoKitAsset.swift */,
|
||||
);
|
||||
name = Photos;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F26775DF1C704574002E786C /* AnimationController */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F26775E41C70574F002E786C /* AnimatableNavigationController.swift */,
|
||||
F26775E01C7046C7002E786C /* ExpandingAnimationController.swift */,
|
||||
F26775E91C71645A002E786C /* ContractingAnimationController.swift */,
|
||||
F2131F421C79615700797887 /* SwipeInteractionController.swift */,
|
||||
);
|
||||
name = AnimationController;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F26775E61C7073B1002E786C /* Common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F26775DD1C701FA7002E786C /* ItemListType.swift */,
|
||||
F202573B1C7418920069B33A /* PickedAssetList.swift */,
|
||||
F20257391C7343D20069B33A /* ImageName.swift */,
|
||||
F26775E71C7073CD002E786C /* Size.swift */,
|
||||
F2DA29761C7749D600B0A8E3 /* NotificationInfo.swift */,
|
||||
F25C698F1CA27311005935D6 /* EmptyIndicatable.swift */,
|
||||
F23CC89D1CB745C800BCE443 /* ActivityIndicatable.swift */,
|
||||
F25C699A1CA2B79A005935D6 /* ColorConfig.swift */,
|
||||
);
|
||||
name = Common;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F2C08D6A1C68651900B00181 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F2C08D761C68651900B00181 /* NohanaImagePicker */,
|
||||
F2C08D931C688FC400B00181 /* NohanaImagePickerSample */,
|
||||
F2C08DA81C688FC400B00181 /* NohanaImagePickerSampleTests */,
|
||||
F2C08D751C68651900B00181 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F2C08D751C68651900B00181 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F2C08D741C68651900B00181 /* NohanaImagePicker.framework */,
|
||||
F2C08D921C688FC400B00181 /* NohanaImagePickerSample.app */,
|
||||
F2C08DA51C688FC400B00181 /* NohanaImagePickerSampleTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F2C08D761C68651900B00181 /* NohanaImagePicker */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F2C08D771C68651900B00181 /* NohanaImagePicker.h */,
|
||||
F2C08D791C68651900B00181 /* Info.plist */,
|
||||
F26775E61C7073B1002E786C /* Common */,
|
||||
F23554291C69F38900796DCA /* Photos */,
|
||||
F218D7DC1C6C3A3E001FCED1 /* Views */,
|
||||
F2E508901C68B1770082EF93 /* ViewControllers */,
|
||||
F26775DF1C704574002E786C /* AnimationController */,
|
||||
F235541F1C698BE900796DCA /* Resources */,
|
||||
);
|
||||
path = NohanaImagePicker;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F2C08D931C688FC400B00181 /* NohanaImagePickerSample */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F2C08D941C688FC400B00181 /* AppDelegate.swift */,
|
||||
F2C08D961C688FC400B00181 /* ViewController.swift */,
|
||||
F2C08D981C688FC400B00181 /* Main.storyboard */,
|
||||
F2C08D9B1C688FC400B00181 /* Assets.xcassets */,
|
||||
F2C08D9D1C688FC400B00181 /* LaunchScreen.storyboard */,
|
||||
F2C08DA01C688FC400B00181 /* Info.plist */,
|
||||
);
|
||||
path = NohanaImagePickerSample;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F2C08DA81C688FC400B00181 /* NohanaImagePickerSampleTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F2C08DA91C688FC400B00181 /* NohanaImagePickerSampleTests.swift */,
|
||||
F2C08DAB1C688FC400B00181 /* Info.plist */,
|
||||
);
|
||||
path = NohanaImagePickerSampleTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F2E508901C68B1770082EF93 /* ViewControllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F23554271C69D5DB00796DCA /* NohanaImagePickerController.swift */,
|
||||
F24EB68F1C68AEED0002EC86 /* AlbumListViewController.swift */,
|
||||
F2DF3B141C6C76E500C1C0E4 /* AssetListViewController.swift */,
|
||||
F25C10C11C8ED9BF007453C3 /* MomentViewController.swift */,
|
||||
F2DF3B2A1C6CC4DB00C1C0E4 /* AssetDetailListViewController.swift */,
|
||||
);
|
||||
name = ViewControllers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
F2C08D711C68651900B00181 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F2C08D781C68651900B00181 /* NohanaImagePicker.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
F2C08D731C68651900B00181 /* NohanaImagePicker */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = F2C08D881C68651900B00181 /* Build configuration list for PBXNativeTarget "NohanaImagePicker" */;
|
||||
buildPhases = (
|
||||
F2C08D6F1C68651900B00181 /* Sources */,
|
||||
F2C08D701C68651900B00181 /* Frameworks */,
|
||||
F2C08D711C68651900B00181 /* Headers */,
|
||||
F2C08D721C68651900B00181 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = NohanaImagePicker;
|
||||
productName = NohanaImagePicker;
|
||||
productReference = F2C08D741C68651900B00181 /* NohanaImagePicker.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
F2C08D911C688FC400B00181 /* NohanaImagePickerSample */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = F2C08DAC1C688FC400B00181 /* Build configuration list for PBXNativeTarget "NohanaImagePickerSample" */;
|
||||
buildPhases = (
|
||||
F2C08D8E1C688FC400B00181 /* Sources */,
|
||||
F2C08D8F1C688FC400B00181 /* Frameworks */,
|
||||
F2C08D901C688FC400B00181 /* Resources */,
|
||||
F24EB6951C68AFB40002EC86 /* Embed Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
F24EB6941C68AFB40002EC86 /* PBXTargetDependency */,
|
||||
);
|
||||
name = NohanaImagePickerSample;
|
||||
productName = NohanaImagePickerSample;
|
||||
productReference = F2C08D921C688FC400B00181 /* NohanaImagePickerSample.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
F2C08DA41C688FC400B00181 /* NohanaImagePickerSampleTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = F2C08DAF1C688FC400B00181 /* Build configuration list for PBXNativeTarget "NohanaImagePickerSampleTests" */;
|
||||
buildPhases = (
|
||||
F2C08DA11C688FC400B00181 /* Sources */,
|
||||
F2C08DA21C688FC400B00181 /* Frameworks */,
|
||||
F2C08DA31C688FC400B00181 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
F2C08DA71C688FC400B00181 /* PBXTargetDependency */,
|
||||
);
|
||||
name = NohanaImagePickerSampleTests;
|
||||
productName = NohanaImagePickerSampleTests;
|
||||
productReference = F2C08DA51C688FC400B00181 /* NohanaImagePickerSampleTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
F2C08D6B1C68651900B00181 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0720;
|
||||
LastUpgradeCheck = 0720;
|
||||
ORGANIZATIONNAME = nohana;
|
||||
TargetAttributes = {
|
||||
F2C08D731C68651900B00181 = {
|
||||
CreatedOnToolsVersion = 7.2.1;
|
||||
};
|
||||
F2C08D911C688FC400B00181 = {
|
||||
CreatedOnToolsVersion = 7.2.1;
|
||||
};
|
||||
F2C08DA41C688FC400B00181 = {
|
||||
CreatedOnToolsVersion = 7.2.1;
|
||||
TestTargetID = F2C08D911C688FC400B00181;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = F2C08D6E1C68651900B00181 /* Build configuration list for PBXProject "NohanaImagePicker" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
ja,
|
||||
);
|
||||
mainGroup = F2C08D6A1C68651900B00181;
|
||||
productRefGroup = F2C08D751C68651900B00181 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
F2C08D731C68651900B00181 /* NohanaImagePicker */,
|
||||
F2C08D911C688FC400B00181 /* NohanaImagePickerSample */,
|
||||
F2C08DA41C688FC400B00181 /* NohanaImagePickerSampleTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
F2C08D721C68651900B00181 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F23554261C69D19C00796DCA /* NohanaImagePicker.storyboard in Resources */,
|
||||
F27029CB1C71C43A001647AB /* NohanaImagePicker.strings in Resources */,
|
||||
F237249B1C6DCF96005D1E8A /* Images.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F2C08D901C688FC400B00181 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F2C08D9F1C688FC400B00181 /* LaunchScreen.storyboard in Resources */,
|
||||
F2C08D9C1C688FC400B00181 /* Assets.xcassets in Resources */,
|
||||
F2C08D9A1C688FC400B00181 /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F2C08DA31C688FC400B00181 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
F2C08D6F1C68651900B00181 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F2DF3B171C6C868E00C1C0E4 /* AssetCell.swift in Sources */,
|
||||
F26775E81C7073CD002E786C /* Size.swift in Sources */,
|
||||
F26775DE1C701FA7002E786C /* ItemListType.swift in Sources */,
|
||||
F23CC89E1CB745C800BCE443 /* ActivityIndicatable.swift in Sources */,
|
||||
F202573C1C7418920069B33A /* PickedAssetList.swift in Sources */,
|
||||
F25C10C21C8ED9BF007453C3 /* MomentViewController.swift in Sources */,
|
||||
F25C69881CA23A0A005935D6 /* MomentCell.swift in Sources */,
|
||||
F2FE1F781C901D9400FDBE7B /* MomentSectionHeaderView.swift in Sources */,
|
||||
F202573A1C7343D20069B33A /* ImageName.swift in Sources */,
|
||||
F23554281C69D5DB00796DCA /* NohanaImagePickerController.swift in Sources */,
|
||||
F25C69921CA28728005935D6 /* AlbumListEmptyIndicator.swift in Sources */,
|
||||
F2131F431C79615700797887 /* SwipeInteractionController.swift in Sources */,
|
||||
F2DF3B2D1C6D780100C1C0E4 /* AssetDetailCell.swift in Sources */,
|
||||
F25C69901CA27311005935D6 /* EmptyIndicatable.swift in Sources */,
|
||||
F2DA29771C7749D600B0A8E3 /* NotificationInfo.swift in Sources */,
|
||||
F218D7DE1C6C3A5B001FCED1 /* AlbumCell.swift in Sources */,
|
||||
F26775E11C7046C7002E786C /* ExpandingAnimationController.swift in Sources */,
|
||||
F28F4AC51C6C59A500B7D725 /* PhotoKitAsset.swift in Sources */,
|
||||
F2DF3B151C6C76E500C1C0E4 /* AssetListViewController.swift in Sources */,
|
||||
F26775E51C70574F002E786C /* AnimatableNavigationController.swift in Sources */,
|
||||
F2DF3B2B1C6CC4DB00C1C0E4 /* AssetDetailListViewController.swift in Sources */,
|
||||
F218D7D61C6B3D22001FCED1 /* PhotoKitAlbumList.swift in Sources */,
|
||||
F24EB6901C68AEED0002EC86 /* AlbumListViewController.swift in Sources */,
|
||||
F25C699B1CA2B79A005935D6 /* ColorConfig.swift in Sources */,
|
||||
F28F4AC31C6C49EE00B7D725 /* PhotoKitAssetList.swift in Sources */,
|
||||
F26775EA1C71645A002E786C /* ContractingAnimationController.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F2C08D8E1C688FC400B00181 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F2C08D971C688FC400B00181 /* ViewController.swift in Sources */,
|
||||
F2C08D951C688FC400B00181 /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F2C08DA11C688FC400B00181 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F2C08DAA1C688FC400B00181 /* NohanaImagePickerSampleTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
F24EB6941C68AFB40002EC86 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = F2C08D731C68651900B00181 /* NohanaImagePicker */;
|
||||
targetProxy = F24EB6931C68AFB40002EC86 /* PBXContainerItemProxy */;
|
||||
};
|
||||
F2C08DA71C688FC400B00181 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = F2C08D911C688FC400B00181 /* NohanaImagePickerSample */;
|
||||
targetProxy = F2C08DA61C688FC400B00181 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
F27029CD1C71C43A001647AB /* NohanaImagePicker.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
F27029CC1C71C43A001647AB /* en */,
|
||||
F27029CF1C71C4FE001647AB /* ja */,
|
||||
);
|
||||
name = NohanaImagePicker.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F2C08D981C688FC400B00181 /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
F2C08D991C688FC400B00181 /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F2C08D9D1C688FC400B00181 /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
F2C08D9E1C688FC400B00181 /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
F2C08D861C68651900B00181 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F2C08D871C68651900B00181 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F2C08D891C68651900B00181 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = NohanaImagePicker/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = jp.co.nohana.NohanaImagePicker;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F2C08D8A1C68651900B00181 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = NohanaImagePicker/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = jp.co.nohana.NohanaImagePicker;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F2C08DAD1C688FC400B00181 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
|
||||
INFOPLIST_FILE = NohanaImagePickerSample/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = jp.co.nohana.NohanaImagePickerSample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F2C08DAE1C688FC400B00181 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
|
||||
INFOPLIST_FILE = NohanaImagePickerSample/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = jp.co.nohana.NohanaImagePickerSample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F2C08DB01C688FC400B00181 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
INFOPLIST_FILE = NohanaImagePickerSampleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = jp.co.nohana.NohanaImagePickerSample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NohanaImagePickerSample.app/NohanaImagePickerSample";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F2C08DB11C688FC400B00181 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
INFOPLIST_FILE = NohanaImagePickerSampleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = jp.co.nohana.NohanaImagePickerSample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NohanaImagePickerSample.app/NohanaImagePickerSample";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
F2C08D6E1C68651900B00181 /* Build configuration list for PBXProject "NohanaImagePicker" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F2C08D861C68651900B00181 /* Debug */,
|
||||
F2C08D871C68651900B00181 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F2C08D881C68651900B00181 /* Build configuration list for PBXNativeTarget "NohanaImagePicker" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F2C08D891C68651900B00181 /* Debug */,
|
||||
F2C08D8A1C68651900B00181 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F2C08DAC1C688FC400B00181 /* Build configuration list for PBXNativeTarget "NohanaImagePickerSample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F2C08DAD1C688FC400B00181 /* Debug */,
|
||||
F2C08DAE1C688FC400B00181 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F2C08DAF1C688FC400B00181 /* Build configuration list for PBXNativeTarget "NohanaImagePickerSampleTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F2C08DB01C688FC400B00181 /* Debug */,
|
||||
F2C08DB11C688FC400B00181 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = F2C08D6B1C68651900B00181 /* Project object */;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:NohanaImagePicker.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F2C08D731C68651900B00181"
|
||||
BuildableName = "NohanaImagePicker.framework"
|
||||
BlueprintName = "NohanaImagePicker"
|
||||
ReferencedContainer = "container:NohanaImagePicker.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F2C08D7D1C68651900B00181"
|
||||
BuildableName = "NohanaImagePickerTests.xctest"
|
||||
BlueprintName = "NohanaImagePickerTests"
|
||||
ReferencedContainer = "container:NohanaImagePicker.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F2C08D731C68651900B00181"
|
||||
BuildableName = "NohanaImagePicker.framework"
|
||||
BlueprintName = "NohanaImagePicker"
|
||||
ReferencedContainer = "container:NohanaImagePicker.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F2C08D731C68651900B00181"
|
||||
BuildableName = "NohanaImagePicker.framework"
|
||||
BlueprintName = "NohanaImagePicker"
|
||||
ReferencedContainer = "container:NohanaImagePicker.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F2C08D731C68651900B00181"
|
||||
BuildableName = "NohanaImagePicker.framework"
|
||||
BlueprintName = "NohanaImagePicker"
|
||||
ReferencedContainer = "container:NohanaImagePicker.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F2C08D911C688FC400B00181"
|
||||
BuildableName = "NohanaImagePickerSample.app"
|
||||
BlueprintName = "NohanaImagePickerSample"
|
||||
ReferencedContainer = "container:NohanaImagePicker.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F2C08DA41C688FC400B00181"
|
||||
BuildableName = "NohanaImagePickerSampleTests.xctest"
|
||||
BlueprintName = "NohanaImagePickerSampleTests"
|
||||
ReferencedContainer = "container:NohanaImagePicker.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F2C08D911C688FC400B00181"
|
||||
BuildableName = "NohanaImagePickerSample.app"
|
||||
BlueprintName = "NohanaImagePickerSample"
|
||||
ReferencedContainer = "container:NohanaImagePicker.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F2C08D911C688FC400B00181"
|
||||
BuildableName = "NohanaImagePickerSample.app"
|
||||
BlueprintName = "NohanaImagePickerSample"
|
||||
ReferencedContainer = "container:NohanaImagePicker.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F2C08D911C688FC400B00181"
|
||||
BuildableName = "NohanaImagePickerSample.app"
|
||||
BlueprintName = "NohanaImagePickerSample"
|
||||
ReferencedContainer = "container:NohanaImagePicker.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// ActivityIndicatable.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/04/08.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
public protocol ActivityIndicatable {
|
||||
func isProgressing() -> Bool
|
||||
func updateVisibilityOfActivityIndicator(activityIndicator: UIView)
|
||||
}
|
||||
|
||||
public extension ActivityIndicatable where Self: UIViewController {
|
||||
func updateVisibilityOfActivityIndicator(activityIndicator: UIView) {
|
||||
if isProgressing() {
|
||||
if !view.subviews.contains(activityIndicator) {
|
||||
view.addSubview(activityIndicator)
|
||||
}
|
||||
} else {
|
||||
activityIndicator.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// AlbumCell.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/11.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class AlbumCell: UITableViewCell {
|
||||
@IBOutlet weak var thumbnailImageView: UIImageView!
|
||||
@IBOutlet weak var titleLabel: UILabel!
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// AlbumListEmptyIndicator.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/03/23.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
class AlbumListEmptyIndicator: UILabel {
|
||||
|
||||
init(message: String, description: String, frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
let centerStyle = NSMutableParagraphStyle()
|
||||
centerStyle.alignment = NSTextAlignment.Center
|
||||
|
||||
let messageAttributes = [
|
||||
NSForegroundColorAttributeName : ColorConfig.emptyIndicator,
|
||||
NSFontAttributeName : UIFont.systemFontOfSize(26),
|
||||
NSParagraphStyleAttributeName : centerStyle
|
||||
]
|
||||
let messageText = NSAttributedString(string: message, attributes: messageAttributes)
|
||||
|
||||
let descriptionAttributes = [
|
||||
NSForegroundColorAttributeName : ColorConfig.emptyIndicator,
|
||||
NSFontAttributeName : UIFont.systemFontOfSize(14),
|
||||
NSParagraphStyleAttributeName : centerStyle
|
||||
]
|
||||
let descriptionText = NSAttributedString(string: description, attributes: descriptionAttributes)
|
||||
|
||||
let attributedText = NSMutableAttributedString()
|
||||
attributedText.appendAttributedString(messageText)
|
||||
attributedText.appendAttributedString(NSAttributedString(string: "\n\n", attributes: [NSFontAttributeName : UIFont.systemFontOfSize(6)]))
|
||||
attributedText.appendAttributedString(descriptionText)
|
||||
|
||||
self.numberOfLines = 0
|
||||
self.attributedText = attributedText
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
//
|
||||
// AlbumListViewController.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/08.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Photos
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
class AlbumListViewController: UITableViewController, EmptyIndicatable, ActivityIndicatable {
|
||||
|
||||
weak var nohanaImagePickerController: NohanaImagePickerController?
|
||||
var photoKitAlbumList: PhotoKitAlbumList!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
title = NSLocalizedString("albumlist.title", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController!.assetBundle, comment: "")
|
||||
setUpToolbarItems()
|
||||
navigationController?.setToolbarHidden(nohanaImagePickerController?.toolbarHidden ?? false, animated: false)
|
||||
setUpEmptyIndicator()
|
||||
setUpActivityIndicator()
|
||||
self.view.backgroundColor = ColorConfig.backgroundColor
|
||||
}
|
||||
|
||||
deinit {
|
||||
NSNotificationCenter.defaultCenter().removeObserver(self)
|
||||
}
|
||||
|
||||
override func viewWillAppear(animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
setToolbarTitle(nohanaImagePickerController)
|
||||
if let indexPathForSelectedRow = tableView.indexPathForSelectedRow {
|
||||
tableView.deselectRowAtIndexPath(indexPathForSelectedRow, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UITableViewDelegate
|
||||
|
||||
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
|
||||
guard let nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return
|
||||
}
|
||||
if isMomentRow(indexPath) {
|
||||
nohanaImagePickerController.delegate?.nohanaImagePickerDidSelectMoment?(nohanaImagePickerController)
|
||||
} else {
|
||||
nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, didSelectPhotoKitAssetList: photoKitAlbumList[exactRow(indexPath)].assetList)
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
|
||||
guard let nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return 0
|
||||
}
|
||||
if nohanaImagePickerController.shouldShowMoment && indexPath.row == 0 {
|
||||
return 52
|
||||
}
|
||||
return 82
|
||||
}
|
||||
|
||||
// MARK: - UITableViewDataSource
|
||||
|
||||
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
if let emptyIndicator = emptyIndicator {
|
||||
updateVisibilityOfEmptyIndicator(emptyIndicator)
|
||||
}
|
||||
if let activityIndicator = activityIndicator {
|
||||
updateVisibilityOfActivityIndicator(activityIndicator)
|
||||
}
|
||||
|
||||
guard nohanaImagePickerController?.shouldShowMoment ?? false else {
|
||||
return photoKitAlbumList.count
|
||||
}
|
||||
return photoKitAlbumList.count != 0 ? photoKitAlbumList.count + 1 : 0
|
||||
}
|
||||
|
||||
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
|
||||
guard !isMomentRow(indexPath) else {
|
||||
guard let cell = tableView.dequeueReusableCellWithIdentifier("MomentAlbumCell") as? AlbumCell else {
|
||||
fatalError("failed to dequeueReusableCellWithIdentifier(\"MomentAlbumCell\")")
|
||||
}
|
||||
cell.titleLabel?.text = NSLocalizedString("albumlist.moment.title", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController!.assetBundle, comment: "")
|
||||
return cell
|
||||
}
|
||||
|
||||
guard let cell = tableView.dequeueReusableCellWithIdentifier("AlbumCell") as? AlbumCell else {
|
||||
fatalError("failed to dequeueReusableCellWithIdentifier(\"AlbumCell\")")
|
||||
}
|
||||
let albumList = photoKitAlbumList[exactRow(indexPath)]
|
||||
cell.titleLabel.text = albumList.title
|
||||
cell.tag = exactRow(indexPath)
|
||||
let imageSize = CGSize(
|
||||
width: cell.thumbnailImageView.frame.size.width * UIScreen.mainScreen().scale,
|
||||
height: cell.thumbnailImageView.frame.size.width * UIScreen.mainScreen().scale
|
||||
)
|
||||
if let lastAsset = albumList.last {
|
||||
lastAsset.image(imageSize, handler: { (imageData) -> Void in
|
||||
dispatch_async(dispatch_get_main_queue(), { () -> Void in
|
||||
if let imageData = imageData {
|
||||
if cell.tag == self.exactRow(indexPath) {
|
||||
cell.thumbnailImageView.image = imageData.image
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
cell.thumbnailImageView.image = nil
|
||||
}
|
||||
return cell
|
||||
}
|
||||
|
||||
// MARK: - Storyboard
|
||||
|
||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
|
||||
guard let nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return
|
||||
}
|
||||
|
||||
if isMomentRow(tableView.indexPathForSelectedRow!) {
|
||||
let momentViewController = segue.destinationViewController as! MomentViewController
|
||||
momentViewController.nohanaImagePickerController = nohanaImagePickerController
|
||||
momentViewController.momentAlbumList = PhotoKitAlbumList(
|
||||
assetCollectionTypes: [.Moment],
|
||||
assetCollectionSubtypes: [.Any],
|
||||
mediaType: nohanaImagePickerController.mediaType,
|
||||
shouldShowEmptyAlbum: nohanaImagePickerController.shouldShowEmptyAlbum,
|
||||
handler: { () -> Void in
|
||||
dispatch_async(dispatch_get_main_queue(), { () -> Void in
|
||||
momentViewController.isLoading = false
|
||||
momentViewController.collectionView?.reloadData()
|
||||
})
|
||||
})
|
||||
} else {
|
||||
let assetListViewController = segue.destinationViewController as! AssetListViewController
|
||||
assetListViewController.photoKitAssetList = photoKitAlbumList[exactRow(tableView.indexPathForSelectedRow!)]
|
||||
assetListViewController.nohanaImagePickerController = nohanaImagePickerController
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - IBAction
|
||||
|
||||
@IBAction func didPushCancel(sender: AnyObject) {
|
||||
guard let nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return
|
||||
}
|
||||
nohanaImagePickerController.delegate?.nohanaImagePickerDidCancel(nohanaImagePickerController)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func exactRow(indexPath: NSIndexPath) -> Int {
|
||||
guard nohanaImagePickerController?.shouldShowMoment ?? false else {
|
||||
return indexPath.row
|
||||
}
|
||||
return indexPath.row - 1
|
||||
}
|
||||
|
||||
private func isMomentRow(indexPath: NSIndexPath) -> Bool {
|
||||
return indexPath.row == 0 && (nohanaImagePickerController?.shouldShowMoment ?? false)
|
||||
}
|
||||
|
||||
// MARK: - EmptyIndicatable
|
||||
|
||||
var emptyIndicator: UIView?
|
||||
|
||||
func setUpEmptyIndicator() {
|
||||
let frame = CGRect(origin: CGPoint.zero, size: Size.screenRectWithoutAppBar(self).size)
|
||||
emptyIndicator = AlbumListEmptyIndicator(
|
||||
message: NSLocalizedString("albumlist.empty.message", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController!.assetBundle, comment: ""),
|
||||
description: NSLocalizedString("albumlist.empty.description", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController!.assetBundle, comment: ""),
|
||||
frame: frame)
|
||||
}
|
||||
|
||||
func isEmpty() -> Bool {
|
||||
if isProgressing() {
|
||||
return false
|
||||
}
|
||||
return photoKitAlbumList.count == 0
|
||||
}
|
||||
|
||||
// MARK: - ActivityIndicatable
|
||||
|
||||
var activityIndicator: UIActivityIndicatorView?
|
||||
var isLoading = true
|
||||
|
||||
func setUpActivityIndicator() {
|
||||
activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .Gray)
|
||||
let screenRect = Size.screenRectWithoutAppBar(self)
|
||||
activityIndicator?.center = CGPoint(x: screenRect.size.width / 2, y: screenRect.size.height / 2)
|
||||
activityIndicator?.startAnimating()
|
||||
}
|
||||
|
||||
func isProgressing() -> Bool {
|
||||
return isLoading
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
extension UIViewController {
|
||||
|
||||
// MARK: - Toolbar
|
||||
|
||||
func setUpToolbarItems() {
|
||||
let leftSpace = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
|
||||
let rightSpace = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
|
||||
|
||||
let infoButton = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
|
||||
infoButton.enabled = false
|
||||
infoButton.setTitleTextAttributes([NSFontAttributeName: UIFont.systemFontOfSize(14), NSForegroundColorAttributeName: UIColor.blackColor()], forState: .Normal)
|
||||
self.toolbarItems = [leftSpace, infoButton, rightSpace]
|
||||
}
|
||||
|
||||
func setToolbarTitle(nohanaImagePickerController:NohanaImagePickerController?) {
|
||||
guard toolbarItems?.count >= 2 else {
|
||||
return
|
||||
}
|
||||
guard
|
||||
let infoButton = toolbarItems?[1],
|
||||
let nohanaImagePickerController = nohanaImagePickerController
|
||||
else {
|
||||
return
|
||||
}
|
||||
if nohanaImagePickerController.maximumNumberOfSelection == 0 {
|
||||
let title = String(format: NSLocalizedString("toolbar.title.nolimit", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController.assetBundle, comment: ""),
|
||||
nohanaImagePickerController.pickedAssetList.count)
|
||||
infoButton.title = title
|
||||
} else {
|
||||
let title = String(format: NSLocalizedString("toolbar.title.haslimit", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController.assetBundle, comment: ""),
|
||||
nohanaImagePickerController.pickedAssetList.count,
|
||||
nohanaImagePickerController.maximumNumberOfSelection)
|
||||
infoButton.title = title
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Notification
|
||||
|
||||
func addPickPhotoKitAssetNotificationObservers() {
|
||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: "didPickPhotoKitAsset:", name: NotificationInfo.Asset.PhotoKit.didPick, object: nil)
|
||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: "didDropPhotoKitAsset:", name: NotificationInfo.Asset.PhotoKit.didDrop, object: nil)
|
||||
}
|
||||
|
||||
func didPickPhotoKitAsset(notification: NSNotification) {
|
||||
guard let picker = notification.object as? NohanaImagePickerController else {
|
||||
return
|
||||
}
|
||||
setToolbarTitle(picker)
|
||||
}
|
||||
|
||||
func didDropPhotoKitAsset(notification: NSNotification) {
|
||||
guard let picker = notification.object as? NohanaImagePickerController else {
|
||||
return
|
||||
}
|
||||
setToolbarTitle(picker)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// AnimatableNavigationController.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/14.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
class AnimatableNavigationController: UINavigationController, UINavigationControllerDelegate, UIViewControllerTransitioningDelegate {
|
||||
|
||||
let swipeInteractionController = SwipeInteractionController()
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
self.delegate = self
|
||||
}
|
||||
|
||||
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||
|
||||
switch operation {
|
||||
case .Push where fromVC is AssetListViewController:
|
||||
guard let fromVC = fromVC as? AssetListViewController,
|
||||
selectedIndex = fromVC.collectionView?.indexPathsForSelectedItems()?.first,
|
||||
fromCell = fromVC.collectionView?.cellForItemAtIndexPath(selectedIndex) as? AssetCell
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
return ExpandingAnimationController(fromCell: fromCell)
|
||||
case .Pop where fromVC is AssetDetailListViewController:
|
||||
guard let fromVC = fromVC as? AssetDetailListViewController,
|
||||
fromCell = fromVC.collectionView?.cellForItemAtIndexPath(fromVC.currentIndexPath) as? AssetDetailCell
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
return ContractingAnimationController(fromCell: fromCell)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
|
||||
swipeInteractionController.attachToViewController(viewController)
|
||||
}
|
||||
|
||||
func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
|
||||
if animationController is ExpandingAnimationController {
|
||||
return nil
|
||||
}
|
||||
if animationController is ContractingAnimationController {
|
||||
return nil
|
||||
}
|
||||
return swipeInteractionController
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// AssetCell.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/11.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
class AssetCell: UICollectionViewCell {
|
||||
|
||||
@IBOutlet weak var imageView: UIImageView!
|
||||
@IBOutlet weak var pickButton: UIButton!
|
||||
@IBOutlet weak var overlayView: UIView!
|
||||
|
||||
weak var nohanaImagePickerController: NohanaImagePickerController?
|
||||
var asset: AssetType?
|
||||
|
||||
override func willMoveToSuperview(newSuperview: UIView?) {
|
||||
super.willMoveToSuperview(newSuperview)
|
||||
|
||||
pickButton.setImage(
|
||||
UIImage(named: ImageName.AssetCell.PickButton.SizeM.dropped, inBundle: nohanaImagePickerController?.assetBundle, compatibleWithTraitCollection: nil),
|
||||
forState: .Normal)
|
||||
pickButton.setImage(
|
||||
UIImage(named: ImageName.AssetCell.PickButton.SizeM.picked, inBundle: nohanaImagePickerController?.assetBundle, compatibleWithTraitCollection: nil),
|
||||
forState: [.Normal, .Selected])
|
||||
}
|
||||
|
||||
@IBAction func didPushPickButton(sender: UIButton) {
|
||||
guard let asset = asset, nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return
|
||||
}
|
||||
if pickButton.selected {
|
||||
if nohanaImagePickerController.pickedAssetList.dropAsset(asset) {
|
||||
pickButton.selected = false
|
||||
}
|
||||
} else {
|
||||
if nohanaImagePickerController.pickedAssetList.pickAsset(asset) {
|
||||
pickButton.selected = true
|
||||
}
|
||||
}
|
||||
self.overlayView.hidden = !pickButton.selected
|
||||
}
|
||||
|
||||
func update(asset: AssetType, nohanaImagePickerController: NohanaImagePickerController?) {
|
||||
self.asset = asset
|
||||
self.nohanaImagePickerController = nohanaImagePickerController
|
||||
self.pickButton.selected = nohanaImagePickerController?.pickedAssetList.isPicked(asset) ?? false
|
||||
self.overlayView.hidden = !pickButton.selected
|
||||
self.pickButton.hidden = !(nohanaImagePickerController?.canPickAsset(asset) ?? true)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// AssetDetailCell.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/12.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class AssetDetailCell: UICollectionViewCell, UIScrollViewDelegate {
|
||||
|
||||
@IBOutlet weak var scrollView: UIScrollView!
|
||||
@IBOutlet weak var imageView: UIImageView!
|
||||
|
||||
@IBOutlet weak var imageViewHeightConstraint: NSLayoutConstraint!
|
||||
@IBOutlet weak var imageViewWidthConstraint: NSLayoutConstraint!
|
||||
let doubleTapGestureRecognizer :UITapGestureRecognizer = UITapGestureRecognizer()
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
doubleTapGestureRecognizer.addTarget(self, action: "didDoubleTap:")
|
||||
doubleTapGestureRecognizer.numberOfTapsRequired = 2
|
||||
}
|
||||
|
||||
override func willMoveToSuperview(newSuperview: UIView?) {
|
||||
super.willMoveToSuperview(newSuperview)
|
||||
scrollView.removeGestureRecognizer(doubleTapGestureRecognizer)
|
||||
scrollView.addGestureRecognizer(doubleTapGestureRecognizer)
|
||||
}
|
||||
|
||||
deinit {
|
||||
scrollView.removeGestureRecognizer(doubleTapGestureRecognizer)
|
||||
doubleTapGestureRecognizer.removeTarget(self, action: "didDoubleTap:")
|
||||
}
|
||||
|
||||
// MARK: - UIScrollViewDelegate
|
||||
|
||||
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
|
||||
return imageView
|
||||
}
|
||||
|
||||
// MARK: - Zoom
|
||||
|
||||
func didDoubleTap(sender: UITapGestureRecognizer) {
|
||||
if scrollView.zoomScale < scrollView.maximumZoomScale {
|
||||
let center = sender.locationInView(imageView)
|
||||
scrollView.zoomToRect(zoomRect(center), animated: true)
|
||||
} else {
|
||||
let defaultScale: CGFloat = 1
|
||||
scrollView.setZoomScale(defaultScale, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
func zoomRect(center: CGPoint) -> CGRect {
|
||||
var zoomRect: CGRect = CGRect()
|
||||
zoomRect.size.height = scrollView.frame.size.height / scrollView.maximumZoomScale
|
||||
zoomRect.size.width = scrollView.frame.size.width / scrollView.maximumZoomScale
|
||||
|
||||
zoomRect.origin.x = center.x - zoomRect.size.width / 2.0
|
||||
zoomRect.origin.y = center.y - zoomRect.size.height / 2.0
|
||||
|
||||
return zoomRect
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
//
|
||||
// AssetDetailListViewController.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/11.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
class AssetDetailListViewController: AssetListViewController {
|
||||
|
||||
var selectedIndexPath:NSIndexPath!
|
||||
var currentIndexPath: NSIndexPath = NSIndexPath() {
|
||||
willSet {
|
||||
if currentIndexPath != newValue {
|
||||
didChangeAssetDetailPage(newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
@IBOutlet weak var pickButton: UIButton!
|
||||
|
||||
override var cellSize: CGSize {
|
||||
get {
|
||||
return Size.screenRectWithoutAppBar(self).size
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
pickButton.setImage(
|
||||
UIImage(named: ImageName.AssetCell.PickButton.SizeL.dropped, inBundle: nohanaImagePickerController?.assetBundle, compatibleWithTraitCollection: nil),
|
||||
forState: .Normal)
|
||||
pickButton.setImage(
|
||||
UIImage(named: ImageName.AssetCell.PickButton.SizeL.picked, inBundle: nohanaImagePickerController?.assetBundle, compatibleWithTraitCollection: nil),
|
||||
forState: [.Normal, .Selected])
|
||||
}
|
||||
|
||||
override func viewWillAppear(animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
}
|
||||
|
||||
override func updateTitle() {
|
||||
self.title = ""
|
||||
}
|
||||
|
||||
func didChangeAssetDetailPage(indexPath:NSIndexPath) {
|
||||
let asset = photoKitAssetList[indexPath.item]
|
||||
pickButton.selected = nohanaImagePickerController?.pickedAssetList.isPicked(asset) ?? false
|
||||
pickButton.hidden = !(nohanaImagePickerController?.canPickAsset(asset) ?? true)
|
||||
guard let nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return
|
||||
}
|
||||
nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, assetDetailListViewController: self, didChangeAssetDetailPage: indexPath, photoKitAsset: asset.originalAsset)
|
||||
}
|
||||
|
||||
override func scrollCollectionViewToInitialPosition() {
|
||||
guard isFirstAppearance else {
|
||||
return
|
||||
}
|
||||
isFirstAppearance = false
|
||||
guard photoKitAssetList.count > 0 else {
|
||||
return
|
||||
}
|
||||
collectionView?.scrollToItemAtIndexPath(self.selectedIndexPath, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: false)
|
||||
}
|
||||
|
||||
// MARK: - IBAction
|
||||
|
||||
@IBAction func didPushPickButton(sender: UIButton) {
|
||||
guard let nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return
|
||||
}
|
||||
let asset = photoKitAssetList[currentIndexPath.row]
|
||||
if pickButton.selected {
|
||||
if nohanaImagePickerController.pickedAssetList.dropAsset(asset) {
|
||||
pickButton.selected = false
|
||||
}
|
||||
} else {
|
||||
if nohanaImagePickerController.pickedAssetList.pickAsset(asset) {
|
||||
pickButton.selected = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UICollectionViewDelegate
|
||||
|
||||
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
|
||||
guard let cell = collectionView.dequeueReusableCellWithReuseIdentifier("AssetDetailCell", forIndexPath: indexPath) as? AssetDetailCell,
|
||||
nohanaImagePickerController = nohanaImagePickerController
|
||||
else {
|
||||
return UICollectionViewCell(frame: CGRectZero)
|
||||
}
|
||||
cell.scrollView.zoomScale = 1
|
||||
cell.tag = indexPath.item
|
||||
|
||||
let imageSize = CGSize(
|
||||
width: cellSize.width * UIScreen.mainScreen().scale,
|
||||
height: cellSize.height * UIScreen.mainScreen().scale
|
||||
)
|
||||
let asset = photoKitAssetList[indexPath.item]
|
||||
asset.image(imageSize) { (imageData) -> Void in
|
||||
dispatch_async(dispatch_get_main_queue(), { () -> Void in
|
||||
if let imageData = imageData {
|
||||
if cell.tag == indexPath.item {
|
||||
cell.imageView.image = imageData.image
|
||||
cell.imageViewHeightConstraint.constant = self.cellSize.height
|
||||
cell.imageViewWidthConstraint.constant = self.cellSize.width
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return (nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, assetDetailListViewController: self, cell: cell, indexPath: indexPath, photoKitAsset: asset.originalAsset)) ?? cell
|
||||
}
|
||||
|
||||
// MARK: - UIScrollViewDelegate
|
||||
|
||||
override func scrollViewDidScroll(scrollView: UIScrollView) {
|
||||
guard let collectionView = collectionView else {
|
||||
return
|
||||
}
|
||||
let row = Int((collectionView.contentOffset.x + cellSize.width * 0.5) / cellSize.width)
|
||||
currentIndexPath = NSIndexPath(forRow: row, inSection: 0)
|
||||
}
|
||||
|
||||
// MARK: - UICollectionViewDelegateFlowLayout
|
||||
|
||||
override func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
|
||||
return cellSize
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
//
|
||||
// AssetListViewController.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/11.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Photos
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
class AssetListViewController: UICollectionViewController {
|
||||
|
||||
weak var nohanaImagePickerController: NohanaImagePickerController?
|
||||
var photoKitAssetList: PhotoKitAssetList!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
updateTitle()
|
||||
setUpToolbarItems()
|
||||
addPickPhotoKitAssetNotificationObservers()
|
||||
self.view.backgroundColor = ColorConfig.backgroundColor
|
||||
}
|
||||
|
||||
var cellSize: CGSize {
|
||||
get {
|
||||
guard let nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return CGSize.zero
|
||||
}
|
||||
var numberOfColumns = nohanaImagePickerController.numberOfColumnsInLandscape
|
||||
if UIInterfaceOrientationIsPortrait(UIApplication.sharedApplication().statusBarOrientation) {
|
||||
numberOfColumns = nohanaImagePickerController.numberOfColumnsInPortrait
|
||||
}
|
||||
let cellMargin:CGFloat = 2
|
||||
let cellWidth = (view.frame.width - cellMargin * (CGFloat(numberOfColumns) - 1)) / CGFloat(numberOfColumns)
|
||||
return CGSize(width: cellWidth, height: cellWidth)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
NSNotificationCenter.defaultCenter().removeObserver(self)
|
||||
}
|
||||
|
||||
override func viewWillAppear(animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
setToolbarTitle(nohanaImagePickerController)
|
||||
collectionView?.reloadData()
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
scrollCollectionViewToInitialPosition()
|
||||
}
|
||||
|
||||
var isFirstAppearance = true
|
||||
|
||||
func updateTitle() {
|
||||
title = photoKitAssetList.title
|
||||
}
|
||||
|
||||
func scrollCollectionViewToInitialPosition() {
|
||||
guard isFirstAppearance else {
|
||||
return
|
||||
}
|
||||
guard photoKitAssetList.count > 0 else {
|
||||
return
|
||||
}
|
||||
let index = NSIndexPath(forRow: self.photoKitAssetList.count - 1, inSection: 0)
|
||||
collectionView?.scrollToItemAtIndexPath(index, atScrollPosition: .Bottom, animated: false)
|
||||
|
||||
isFirstAppearance = false
|
||||
}
|
||||
|
||||
// MARK: - UICollectionViewDataSource
|
||||
|
||||
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return photoKitAssetList.count
|
||||
}
|
||||
|
||||
// MARK: - UICollectionViewDelegate
|
||||
|
||||
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
|
||||
guard let nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return
|
||||
}
|
||||
nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, didSelectPhotoKitAsset: photoKitAssetList[indexPath.item].originalAsset)
|
||||
}
|
||||
|
||||
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
|
||||
guard let cell = collectionView.dequeueReusableCellWithReuseIdentifier("AssetCell", forIndexPath: indexPath) as? AssetCell,
|
||||
nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return UICollectionViewCell(frame: CGRectZero)
|
||||
}
|
||||
cell.tag = indexPath.item
|
||||
cell.update(photoKitAssetList[indexPath.row], nohanaImagePickerController: nohanaImagePickerController)
|
||||
|
||||
let imageSize = CGSize(
|
||||
width: cellSize.width * UIScreen.mainScreen().scale,
|
||||
height: cellSize.height * UIScreen.mainScreen().scale
|
||||
)
|
||||
let asset = photoKitAssetList[indexPath.item]
|
||||
asset.image(imageSize) { (imageData) -> Void in
|
||||
dispatch_async(dispatch_get_main_queue(), { () -> Void in
|
||||
if let imageData = imageData {
|
||||
if cell.tag == indexPath.item {
|
||||
cell.imageView.image = imageData.image
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return (nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, assetListViewController: self, cell: cell, indexPath: indexPath, photoKitAsset: asset.originalAsset)) ?? cell
|
||||
}
|
||||
|
||||
// MARK: - UICollectionViewDelegateFlowLayout
|
||||
|
||||
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
|
||||
return cellSize
|
||||
}
|
||||
|
||||
// MARK: - Storyboard
|
||||
|
||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
|
||||
let assetListDetailViewController = segue.destinationViewController as! AssetDetailListViewController
|
||||
assetListDetailViewController.photoKitAssetList = photoKitAssetList
|
||||
assetListDetailViewController.nohanaImagePickerController = nohanaImagePickerController
|
||||
assetListDetailViewController.selectedIndexPath = collectionView?.indexPathsForSelectedItems()?.first
|
||||
}
|
||||
|
||||
// MARK: - IBAction
|
||||
@IBAction func didPushDone(sender: AnyObject) {
|
||||
guard let nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return
|
||||
}
|
||||
|
||||
let pickedPhotoKitAssets = nohanaImagePickerController.pickedAssetList.map{ ($0 as! PhotoKitAsset).originalAsset }
|
||||
nohanaImagePickerController.delegate?.nohanaImagePicker(nohanaImagePickerController, didFinishPickingPhotoKitAssets: pickedPhotoKitAssets )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// ColorConfig.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/03/23.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
public struct ColorConfig {
|
||||
public static var backgroundColor = UIColor.whiteColor()
|
||||
public static var emptyIndicator = UIColor(red: 0x88/0xff, green: 0x88/0xff, blue: 0x88/0xff, alpha: 1)
|
||||
|
||||
public struct AlbumList {
|
||||
public static var momentCellSeparator = UIColor(red: 0xbb/0xff, green: 0xbb/0xff, blue: 0xbb/0xff, alpha: 1)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
//
|
||||
// ContractingAnimationController.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/15.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import AVFoundation
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
extension Size {
|
||||
static func contractingAnimationToCellRect(toVC: AssetListViewController, toCell: AssetCell) -> CGRect {
|
||||
let origin = CGPoint(x: toCell.frame.origin.x, y: toCell.frame.origin.y - toVC.collectionView!.contentOffset.y)
|
||||
return CGRect(origin: origin, size: toCell.frame.size)
|
||||
}
|
||||
|
||||
static func contractingAnimationFromCellRect(fromVC: AssetDetailListViewController, fromCell: AssetDetailCell, contractingImageSize: CGSize) -> CGRect {
|
||||
var rect = AVMakeRectWithAspectRatioInsideRect(contractingImageSize, fromCell.imageView.frame)
|
||||
rect.origin.y += Size.appBarHeight(fromVC)
|
||||
rect.origin.x -= fromCell.scrollView.contentOffset.x
|
||||
rect.origin.y -= fromCell.scrollView.contentOffset.y
|
||||
return rect
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
class ContractingAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
|
||||
|
||||
var fromCell: AssetDetailCell
|
||||
|
||||
init(fromCell: AssetDetailCell) {
|
||||
self.fromCell = fromCell
|
||||
}
|
||||
|
||||
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
|
||||
return 0.3
|
||||
}
|
||||
|
||||
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
|
||||
guard
|
||||
let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as? AssetDetailListViewController,
|
||||
toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as? AssetListViewController,
|
||||
containerView = transitionContext.containerView(),
|
||||
fromCellIndex = fromVC.collectionView?.indexPathForCell(fromCell)
|
||||
else {
|
||||
return
|
||||
}
|
||||
|
||||
var toCellTmp = toVC.collectionView?.cellForItemAtIndexPath(fromCellIndex) as? AssetCell
|
||||
if toCellTmp == nil {
|
||||
// if toCell is not shown in collection view, scroll collection view to toCell index path.
|
||||
toVC.collectionView?.scrollToItemAtIndexPath(fromVC.currentIndexPath, atScrollPosition: .CenteredVertically, animated: false)
|
||||
toVC.collectionView?.layoutIfNeeded()
|
||||
toCellTmp = toVC.collectionView?.cellForItemAtIndexPath(fromCellIndex) as? AssetCell
|
||||
}
|
||||
|
||||
guard let toCell = toCellTmp else {
|
||||
return
|
||||
}
|
||||
|
||||
let contractingImageView = UIImageView(image: fromCell.imageView.image)
|
||||
contractingImageView.contentMode = toCell.imageView.contentMode
|
||||
contractingImageView.clipsToBounds = true
|
||||
contractingImageView.frame = Size.contractingAnimationFromCellRect(fromVC, fromCell: fromCell, contractingImageSize: contractingImageView.image!.size)
|
||||
|
||||
containerView.addSubview(toVC.view)
|
||||
containerView.addSubview(contractingImageView)
|
||||
toVC.view.alpha = 0
|
||||
fromCell.alpha = 0
|
||||
toCell.alpha = 0
|
||||
|
||||
UIView.animateWithDuration(
|
||||
transitionDuration(transitionContext),
|
||||
delay: 0,
|
||||
options: .CurveEaseInOut,
|
||||
animations: { () -> Void in
|
||||
toVC.view.alpha = 1
|
||||
contractingImageView.frame = Size.contractingAnimationToCellRect(toVC, toCell: toCell)
|
||||
}) { (_) -> Void in
|
||||
self.fromCell.alpha = 1
|
||||
toCell.alpha = 1
|
||||
contractingImageView.removeFromSuperview()
|
||||
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// EmptyIndicatable.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/03/23.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
public protocol EmptyIndicatable {
|
||||
func isEmpty() -> Bool
|
||||
func updateVisibilityOfEmptyIndicator(emptyIndicator: UIView)
|
||||
}
|
||||
|
||||
public extension EmptyIndicatable where Self: UIViewController {
|
||||
func updateVisibilityOfEmptyIndicator(emptyIndicator: UIView) {
|
||||
if isEmpty(){
|
||||
if !view.subviews.contains(emptyIndicator) {
|
||||
view.addSubview(emptyIndicator)
|
||||
}
|
||||
} else {
|
||||
emptyIndicator.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// ExpandingAnimationController.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/14.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import AVFoundation
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
extension Size {
|
||||
|
||||
static func expandingAnimationFromCellRect(fromVC: AssetListViewController, fromCell: AssetCell) -> CGRect {
|
||||
let origin = CGPoint(x: fromCell.frame.origin.x, y: fromCell.frame.origin.y - fromVC.collectionView!.contentOffset.y)
|
||||
return CGRect(origin: origin, size: fromCell.frame.size)
|
||||
}
|
||||
|
||||
static func expandingAnimationToCellRect(fromVC: UIViewController, toSize:CGSize) -> CGRect {
|
||||
return AVMakeRectWithAspectRatioInsideRect(toSize, Size.screenRectWithoutAppBar(fromVC))
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
class ExpandingAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
|
||||
|
||||
var fromCell: AssetCell
|
||||
|
||||
init(fromCell: AssetCell) {
|
||||
self.fromCell = fromCell
|
||||
}
|
||||
|
||||
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
|
||||
return 0.3
|
||||
}
|
||||
|
||||
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
|
||||
guard let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as? AssetListViewController,
|
||||
toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as? AssetDetailListViewController,
|
||||
containerView = transitionContext.containerView()
|
||||
else {
|
||||
return
|
||||
}
|
||||
|
||||
let expandingImageView = UIImageView(image: fromCell.imageView.image)
|
||||
expandingImageView.contentMode = fromCell.imageView.contentMode
|
||||
expandingImageView.clipsToBounds = true
|
||||
expandingImageView.frame = Size.expandingAnimationFromCellRect(fromVC, fromCell: fromCell)
|
||||
|
||||
containerView.addSubview(toVC.view)
|
||||
containerView.addSubview(expandingImageView)
|
||||
toVC.view.alpha = 0
|
||||
toVC.collectionView?.hidden = true
|
||||
toVC.view.backgroundColor = UIColor.blackColor()
|
||||
fromCell.alpha = 0
|
||||
|
||||
UIView.animateWithDuration(
|
||||
transitionDuration(transitionContext),
|
||||
delay: 0,
|
||||
usingSpringWithDamping: 0.8,
|
||||
initialSpringVelocity: 10,
|
||||
options: .CurveEaseOut,
|
||||
animations: { () -> Void in
|
||||
toVC.view.alpha = 1
|
||||
expandingImageView.frame = Size.expandingAnimationToCellRect(fromVC, toSize: expandingImageView.image!.size)
|
||||
}) { (_) -> Void in
|
||||
self.fromCell.alpha = 1
|
||||
toVC.collectionView?.hidden = false
|
||||
expandingImageView.removeFromSuperview()
|
||||
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
// ImageName.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/16.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
struct ImageName {
|
||||
struct AssetCell {
|
||||
struct PickButton {
|
||||
struct SizeM {
|
||||
static let picked = "btn_selected_m"
|
||||
static let dropped = "btn_select_m"
|
||||
}
|
||||
struct SizeL {
|
||||
static let picked = "btn_selected_l"
|
||||
static let dropped = "btn_select_l"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "btn_select_l@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "btn_select_l@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
NohanaImagePicker/Images.xcassets/btn_select_l.imageset/btn_select_l@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
NohanaImagePicker/Images.xcassets/btn_select_l.imageset/btn_select_l@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "btn_select_m@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "btn_select_m@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
NohanaImagePicker/Images.xcassets/btn_select_m.imageset/btn_select_m@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
NohanaImagePicker/Images.xcassets/btn_select_m.imageset/btn_select_m@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "btn_selected_l@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "btn_selected_l@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
NohanaImagePicker/Images.xcassets/btn_selected_l.imageset/btn_selected_l@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
NohanaImagePicker/Images.xcassets/btn_selected_l.imageset/btn_selected_l@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "btn_selected_m@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "btn_selected_m@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
NohanaImagePicker/Images.xcassets/btn_selected_m.imageset/btn_selected_m@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
NohanaImagePicker/Images.xcassets/btn_selected_m.imageset/btn_selected_m@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
22
NohanaImagePicker/Images.xcassets/icon_photosize_alert_s.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "icon_photosize_alert_s@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "icon_photosize_alert_s@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
NohanaImagePicker/Images.xcassets/icon_photosize_alert_s.imageset/icon_photosize_alert_s@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
NohanaImagePicker/Images.xcassets/icon_photosize_alert_s.imageset/icon_photosize_alert_s@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
22
NohanaImagePicker/Images.xcassets/icon_photosize_low_s.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "icon_photosize_low_s@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "icon_photosize_low_s@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
NohanaImagePicker/Images.xcassets/icon_photosize_low_s.imageset/icon_photosize_low_s@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
NohanaImagePicker/Images.xcassets/icon_photosize_low_s.imageset/icon_photosize_low_s@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// ItemListType.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/14.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
public protocol ItemListType: CollectionType {
|
||||
typealias Item
|
||||
var title:String { get }
|
||||
func update(handler:(() -> Void)?)
|
||||
subscript (index: Int) -> Item { get }
|
||||
}
|
||||
|
||||
public protocol AssetType {
|
||||
var identifier:Int { get }
|
||||
func image(targetSize:CGSize, handler: (ImageData?) -> Void)
|
||||
}
|
||||
|
||||
public struct ImageData {
|
||||
public var image: UIImage
|
||||
public var info: Dictionary<NSObject, AnyObject>?
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// MomentCell.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/03/23.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class MomentCell: AlbumCell {
|
||||
|
||||
override func drawRect(rect: CGRect) {
|
||||
super.drawRect(rect)
|
||||
let lineWidth: CGFloat = 1 / UIScreen.mainScreen().scale
|
||||
ColorConfig.AlbumList.momentCellSeparator.setFill()
|
||||
UIRectFill(CGRect(x: 16, y: frame.size.height - lineWidth, width: frame.size.width, height:lineWidth))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// MomentSectionHeaderView.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/03/09.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class MomentSectionHeaderView: UICollectionReusableView {
|
||||
|
||||
@IBOutlet weak var dateLabel: UILabel!
|
||||
@IBOutlet weak var locationLabel: UILabel!
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
//
|
||||
// MomentViewController.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/03/08.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Photos
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
class MomentViewController: AssetListViewController, ActivityIndicatable {
|
||||
|
||||
var momentAlbumList: PhotoKitAlbumList!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setUpActivityIndicator()
|
||||
}
|
||||
|
||||
override func updateTitle() {
|
||||
title = NSLocalizedString("albumlist.moment.title", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController!.assetBundle, comment: "")
|
||||
}
|
||||
|
||||
override func scrollCollectionViewToInitialPosition() {
|
||||
guard isFirstAppearance else {
|
||||
return
|
||||
}
|
||||
guard let collectionView = collectionView else {
|
||||
return
|
||||
}
|
||||
let lastSection = momentAlbumList.count - 1
|
||||
guard lastSection >= 0 else {
|
||||
return
|
||||
}
|
||||
|
||||
let index = NSIndexPath(forItem: momentAlbumList[lastSection].count - 1, inSection: lastSection)
|
||||
collectionView.scrollToItemAtIndexPath(index, atScrollPosition: .Bottom, animated: false)
|
||||
isFirstAppearance = false
|
||||
|
||||
}
|
||||
|
||||
// MARK: - UICollectionViewDataSource
|
||||
|
||||
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
|
||||
if let activityIndicator = activityIndicator {
|
||||
updateVisibilityOfActivityIndicator(activityIndicator)
|
||||
}
|
||||
|
||||
return momentAlbumList.count
|
||||
}
|
||||
|
||||
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return momentAlbumList[section].count
|
||||
}
|
||||
|
||||
// MARK: - UICollectionViewDelegate
|
||||
|
||||
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
|
||||
guard let cell = collectionView.dequeueReusableCellWithReuseIdentifier("AssetCell", forIndexPath: indexPath) as? AssetCell,
|
||||
nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return UICollectionViewCell(frame: CGRectZero)
|
||||
}
|
||||
|
||||
let asset = momentAlbumList[indexPath.section][indexPath.row]
|
||||
cell.tag = indexPath.item
|
||||
cell.update(asset, nohanaImagePickerController: nohanaImagePickerController)
|
||||
|
||||
let imageSize = CGSize(
|
||||
width: cellSize.width * UIScreen.mainScreen().scale,
|
||||
height: cellSize.height * UIScreen.mainScreen().scale
|
||||
)
|
||||
asset.image(imageSize) { (imageData) -> Void in
|
||||
dispatch_async(dispatch_get_main_queue(), { () -> Void in
|
||||
if let imageData = imageData {
|
||||
if cell.tag == indexPath.item {
|
||||
cell.imageView.image = imageData.image
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return (nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, assetListViewController: self, cell: cell, indexPath: indexPath, photoKitAsset: asset.originalAsset)) ?? cell
|
||||
}
|
||||
|
||||
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
|
||||
switch kind {
|
||||
case UICollectionElementKindSectionHeader:
|
||||
let album = momentAlbumList[indexPath.section]
|
||||
guard let header = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "MomentHeader", forIndexPath: indexPath) as? MomentSectionHeaderView else {
|
||||
fatalError("failed to create MomentHeader")
|
||||
}
|
||||
header.locationLabel.text = album.title
|
||||
if let date = album.date {
|
||||
let formatter = NSDateFormatter()
|
||||
formatter.dateStyle = .LongStyle
|
||||
formatter.timeStyle = NSDateFormatterStyle.NoStyle
|
||||
header.dateLabel.text = formatter.stringFromDate(date)
|
||||
} else {
|
||||
header.dateLabel.text = ""
|
||||
}
|
||||
return header
|
||||
default:
|
||||
fatalError("failed to create MomentHeader")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ActivityIndicatable
|
||||
|
||||
var activityIndicator: UIActivityIndicatorView?
|
||||
var isLoading = true
|
||||
|
||||
func setUpActivityIndicator() {
|
||||
activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .Gray)
|
||||
let screenRect = Size.screenRectWithoutAppBar(self)
|
||||
activityIndicator?.center = CGPoint(x: screenRect.size.width / 2, y: screenRect.size.height / 2)
|
||||
activityIndicator?.startAnimating()
|
||||
}
|
||||
|
||||
func isProgressing() -> Bool {
|
||||
return isLoading
|
||||
}
|
||||
|
||||
// MARK: - Storyboard
|
||||
|
||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
|
||||
guard let selectedIndexPath = collectionView?.indexPathsForSelectedItems()?.first else {
|
||||
return
|
||||
}
|
||||
|
||||
let assetListDetailViewController = segue.destinationViewController as! AssetDetailListViewController
|
||||
assetListDetailViewController.photoKitAssetList = momentAlbumList[selectedIndexPath.section]
|
||||
assetListDetailViewController.nohanaImagePickerController = nohanaImagePickerController
|
||||
assetListDetailViewController.selectedIndexPath = NSIndexPath(forItem: selectedIndexPath.item, inSection: 0)
|
||||
}
|
||||
|
||||
// MARK: - IBAction
|
||||
|
||||
@IBAction override func didPushDone(sender: AnyObject) {
|
||||
super.didPushDone(sender)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// NohanaImagePicker.h
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/08.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
//! Project version number for NohanaImagePicker.
|
||||
FOUNDATION_EXPORT double NohanaImagePickerVersionNumber;
|
||||
|
||||
//! Project version string for NohanaImagePicker.
|
||||
FOUNDATION_EXPORT const unsigned char NohanaImagePickerVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework
|
||||
// using statements like #import <NohanaImagePicker/PublicHeader.h>
|
||||
|
|
@ -0,0 +1,442 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9532" systemVersion="14F1713" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="tkA-yz-hIq">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9530"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Album List View Controller-->
|
||||
<scene sceneID="q2I-uS-c5w">
|
||||
<objects>
|
||||
<tableViewController id="KD8-91-yw0" customClass="AlbumListViewController" customModule="NohanaImagePicker" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="Nh8-55-S0b">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="AlbumCell" rowHeight="82" id="HiQ-6b-xqZ" customClass="AlbumCell" customModule="NohanaImagePicker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="92" width="320" height="82"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="HiQ-6b-xqZ" id="Nuf-ja-Ajg">
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="82"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Igm-UH-WUI">
|
||||
<rect key="frame" x="12" y="6" width="70" height="70"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="70" id="Vc2-EG-fnZ"/>
|
||||
<constraint firstAttribute="height" constant="70" id="xiw-gz-cfn"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Album Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YSz-MM-h6f">
|
||||
<rect key="frame" x="100" y="33" width="187" height="16"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="16" id="X2y-hP-9aM"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="YSz-MM-h6f" firstAttribute="leading" secondItem="Igm-UH-WUI" secondAttribute="trailing" constant="18" id="LeH-Q7-bwW"/>
|
||||
<constraint firstItem="YSz-MM-h6f" firstAttribute="centerY" secondItem="Nuf-ja-Ajg" secondAttribute="centerY" id="XIa-vC-C0g"/>
|
||||
<constraint firstItem="Igm-UH-WUI" firstAttribute="leading" secondItem="Nuf-ja-Ajg" secondAttribute="leadingMargin" constant="4" id="d1e-N1-R1z"/>
|
||||
<constraint firstItem="Igm-UH-WUI" firstAttribute="centerY" secondItem="Nuf-ja-Ajg" secondAttribute="centerY" id="lNP-fO-Buq"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="YSz-MM-h6f" secondAttribute="trailing" constant="-8" id="tee-FS-sAo"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<connections>
|
||||
<outlet property="thumbnailImageView" destination="Igm-UH-WUI" id="RZo-Jd-deA"/>
|
||||
<outlet property="titleLabel" destination="YSz-MM-h6f" id="bA5-m7-lwo"/>
|
||||
<segue destination="5jk-x3-LYk" kind="show" id="mWT-mj-Xpg"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="MomentAlbumCell" rowHeight="52" id="URZ-ke-kYw" customClass="MomentCell" customModule="NohanaImagePicker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="174" width="320" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="URZ-ke-kYw" id="ZzC-oj-tew">
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Moment Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="nzC-P1-sBf">
|
||||
<rect key="frame" x="16" y="18" width="271" height="16"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="16" id="tPC-2Q-2pd"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="nzC-P1-sBf" secondAttribute="trailing" constant="-8" id="Cg4-Vn-QD9"/>
|
||||
<constraint firstItem="nzC-P1-sBf" firstAttribute="leading" secondItem="ZzC-oj-tew" secondAttribute="leadingMargin" constant="8" id="Gli-fC-Ruq"/>
|
||||
<constraint firstItem="nzC-P1-sBf" firstAttribute="centerY" secondItem="ZzC-oj-tew" secondAttribute="centerY" id="SZH-em-zj3"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<connections>
|
||||
<outlet property="titleLabel" destination="nzC-P1-sBf" id="XE1-Qw-Xid"/>
|
||||
<segue destination="FOz-K3-QuR" kind="show" id="oPR-kG-SaF"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="KD8-91-yw0" id="svJ-EQ-YBS"/>
|
||||
<outlet property="delegate" destination="KD8-91-yw0" id="BME-Rd-OtX"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" id="ldl-4P-wIa">
|
||||
<barButtonItem key="leftBarButtonItem" systemItem="cancel" id="3Gh-FG-2Jq">
|
||||
<connections>
|
||||
<action selector="didPushCancel:" destination="KD8-91-yw0" id="tR3-ZK-z1Y"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<size key="freeformSize" width="320" height="568"/>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="vZM-gg-XY5" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="731" y="449"/>
|
||||
</scene>
|
||||
<!--Asset List View Controller-->
|
||||
<scene sceneID="29G-N1-dd5">
|
||||
<objects>
|
||||
<collectionViewController id="5jk-x3-LYk" customClass="AssetListViewController" customModule="NohanaImagePicker" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="cLH-x9-2VN">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="2" minimumInteritemSpacing="2" id="xXL-vg-bZb">
|
||||
<size key="itemSize" width="50" height="50"/>
|
||||
<size key="headerReferenceSize" width="0.0" height="0.0"/>
|
||||
<size key="footerReferenceSize" width="44" height="44"/>
|
||||
<inset key="sectionInset" minX="0.0" minY="8" maxX="0.0" maxY="2"/>
|
||||
</collectionViewFlowLayout>
|
||||
<cells>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AssetCell" id="gNu-ad-t1d" customClass="AssetCell" customModule="NohanaImagePicker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="72" width="78" height="78"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="78" height="78"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="WKb-lP-sq5">
|
||||
<rect key="frame" x="0.0" y="0.0" width="78" height="78"/>
|
||||
</imageView>
|
||||
<view hidden="YES" alpha="0.29999999999999999" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MT5-kg-1gq">
|
||||
<rect key="frame" x="0.0" y="0.0" width="78" height="78"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="oDB-be-mWY">
|
||||
<rect key="frame" x="34" y="0.0" width="44" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="44" id="7Yd-sj-A9c"/>
|
||||
<constraint firstAttribute="height" constant="44" id="Biw-rC-p8x"/>
|
||||
</constraints>
|
||||
<state key="normal" image="btn_select_m"/>
|
||||
<connections>
|
||||
<action selector="didPushPickButton:" destination="gNu-ad-t1d" eventType="touchUpInside" id="gAj-yS-7xL"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="oDB-be-mWY" secondAttribute="trailing" constant="-8" id="0u6-oO-0PG"/>
|
||||
<constraint firstItem="WKb-lP-sq5" firstAttribute="leading" secondItem="gNu-ad-t1d" secondAttribute="leadingMargin" constant="-8" id="Gen-Gr-Deg"/>
|
||||
<constraint firstItem="oDB-be-mWY" firstAttribute="top" secondItem="gNu-ad-t1d" secondAttribute="topMargin" constant="-8" id="HMs-XU-000"/>
|
||||
<constraint firstItem="MT5-kg-1gq" firstAttribute="top" secondItem="gNu-ad-t1d" secondAttribute="topMargin" constant="-8" id="ISy-ev-P19"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="WKb-lP-sq5" secondAttribute="bottom" constant="-8" id="Lnf-5f-guH"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="MT5-kg-1gq" secondAttribute="trailing" constant="-8" id="QL8-B4-uFE"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="MT5-kg-1gq" secondAttribute="bottom" constant="-8" id="RNL-zl-et0"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="WKb-lP-sq5" secondAttribute="trailing" constant="-8" id="TF3-Wc-2HZ"/>
|
||||
<constraint firstItem="MT5-kg-1gq" firstAttribute="leading" secondItem="gNu-ad-t1d" secondAttribute="leadingMargin" constant="-8" id="afC-Dk-wv1"/>
|
||||
<constraint firstItem="WKb-lP-sq5" firstAttribute="top" secondItem="gNu-ad-t1d" secondAttribute="topMargin" constant="-8" id="l0l-Ge-QIn"/>
|
||||
</constraints>
|
||||
<size key="customSize" width="78" height="78"/>
|
||||
<connections>
|
||||
<outlet property="imageView" destination="WKb-lP-sq5" id="ejZ-cu-f5Y"/>
|
||||
<outlet property="overlayView" destination="MT5-kg-1gq" id="yGO-Ix-xoL"/>
|
||||
<outlet property="pickButton" destination="oDB-be-mWY" id="hf7-6i-k62"/>
|
||||
<segue destination="r7t-t8-AuE" kind="show" id="vma-iJ-kti"/>
|
||||
</connections>
|
||||
</collectionViewCell>
|
||||
</cells>
|
||||
<collectionReusableView key="sectionFooterView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AssetListFooter" id="N6q-ob-hkI">
|
||||
<rect key="frame" x="0.0" y="152" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</collectionReusableView>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="5jk-x3-LYk" id="Wb9-5c-ehn"/>
|
||||
<outlet property="delegate" destination="5jk-x3-LYk" id="DzT-7Y-grc"/>
|
||||
</connections>
|
||||
</collectionView>
|
||||
<navigationItem key="navigationItem" id="2dO-AB-uAb">
|
||||
<barButtonItem key="rightBarButtonItem" systemItem="done" id="mvt-PJ-icK">
|
||||
<connections>
|
||||
<action selector="didPushDone:" destination="5jk-x3-LYk" id="t78-YJ-Taa"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<size key="freeformSize" width="320" height="568"/>
|
||||
</collectionViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="1SX-Sl-Deo" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1156" y="267"/>
|
||||
</scene>
|
||||
<!--Asset Detail List View Controller-->
|
||||
<scene sceneID="jjo-0p-7dH">
|
||||
<objects>
|
||||
<collectionViewController id="r7t-t8-AuE" customClass="AssetDetailListViewController" customModule="NohanaImagePicker" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" pagingEnabled="YES" dataMode="prototypes" id="wIU-KV-n3W">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="KRt-js-xi3">
|
||||
<size key="itemSize" width="320" height="320"/>
|
||||
<size key="headerReferenceSize" width="0.0" height="0.0"/>
|
||||
<size key="footerReferenceSize" width="0.0" height="0.0"/>
|
||||
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
</collectionViewFlowLayout>
|
||||
<cells>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AssetDetailCell" id="Sux-7h-iE6" customClass="AssetDetailCell" customModule="NohanaImagePicker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="156" width="320" height="320"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="320"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" maximumZoomScale="3" translatesAutoresizingMaskIntoConstraints="NO" id="hM8-Xr-3HX">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="320"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Jr7-IN-pxL">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="320"/>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="320" id="6g6-cZ-gPH"/>
|
||||
<constraint firstAttribute="width" constant="320" id="Hgu-gK-eCb"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Jr7-IN-pxL" firstAttribute="top" secondItem="hM8-Xr-3HX" secondAttribute="top" id="Bzv-EL-kt1"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Jr7-IN-pxL" secondAttribute="trailing" id="EjO-pU-R9v"/>
|
||||
<constraint firstItem="Jr7-IN-pxL" firstAttribute="leading" secondItem="hM8-Xr-3HX" secondAttribute="leading" id="Pdy-Fn-ObK"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Jr7-IN-pxL" secondAttribute="bottom" id="QG5-qB-82F"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="Sux-7h-iE6" id="VlX-9M-844"/>
|
||||
</connections>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="hM8-Xr-3HX" secondAttribute="bottom" constant="-8" id="D7T-je-5yG"/>
|
||||
<constraint firstItem="hM8-Xr-3HX" firstAttribute="top" secondItem="Sux-7h-iE6" secondAttribute="topMargin" constant="-8" id="LFL-jM-CYg"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="hM8-Xr-3HX" secondAttribute="trailing" constant="-8" id="ZtL-Jp-e2u"/>
|
||||
<constraint firstItem="hM8-Xr-3HX" firstAttribute="leading" secondItem="Sux-7h-iE6" secondAttribute="leadingMargin" constant="-8" id="yfl-cA-Saf"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="imageView" destination="Jr7-IN-pxL" id="x1X-6p-m21"/>
|
||||
<outlet property="imageViewHeightConstraint" destination="6g6-cZ-gPH" id="rbW-Fe-hPO"/>
|
||||
<outlet property="imageViewWidthConstraint" destination="Hgu-gK-eCb" id="qeL-Vc-jtG"/>
|
||||
<outlet property="scrollView" destination="hM8-Xr-3HX" id="zIr-A1-bmZ"/>
|
||||
</connections>
|
||||
</collectionViewCell>
|
||||
</cells>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="r7t-t8-AuE" id="IF2-zY-xUA"/>
|
||||
<outlet property="delegate" destination="r7t-t8-AuE" id="RAP-Do-LKn"/>
|
||||
</connections>
|
||||
</collectionView>
|
||||
<navigationItem key="navigationItem" id="UuE-5y-0BI">
|
||||
<barButtonItem key="rightBarButtonItem" id="K6j-IO-w2n">
|
||||
<button key="customView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="c4C-Sf-Krj">
|
||||
<rect key="frame" x="276" y="8" width="28" height="28"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" image="btn_select_l"/>
|
||||
<connections>
|
||||
<action selector="didPushPickButton:" destination="r7t-t8-AuE" eventType="touchUpInside" id="vWF-yZ-1NC"/>
|
||||
</connections>
|
||||
</button>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<size key="freeformSize" width="320" height="568"/>
|
||||
<connections>
|
||||
<outlet property="pickButton" destination="c4C-Sf-Krj" id="Bam-Wm-TRa"/>
|
||||
</connections>
|
||||
</collectionViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="u84-ka-8a6" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1598" y="456"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="RR9-zr-Qlw">
|
||||
<objects>
|
||||
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="tkA-yz-hIq" sceneMemberID="viewController">
|
||||
<toolbarItems/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<size key="freeformSize" width="320" height="568"/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="tdZ-Dj-Unr">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<nil name="viewControllers"/>
|
||||
<connections>
|
||||
<segue destination="KD8-91-yw0" kind="relationship" relationship="rootViewController" id="sZ8-aF-u4m"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="3iI-ph-cZF" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="297" y="449"/>
|
||||
</scene>
|
||||
<!--Moment View Controller-->
|
||||
<scene sceneID="kJ6-NP-kmc">
|
||||
<objects>
|
||||
<collectionViewController id="FOz-K3-QuR" customClass="MomentViewController" customModule="NohanaImagePicker" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="J9r-MB-y52">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="2" minimumInteritemSpacing="2" id="smE-Ti-qUX">
|
||||
<size key="itemSize" width="50" height="50"/>
|
||||
<size key="headerReferenceSize" width="50" height="44"/>
|
||||
<size key="footerReferenceSize" width="0.0" height="0.0"/>
|
||||
<inset key="sectionInset" minX="0.0" minY="2" maxX="0.0" maxY="10"/>
|
||||
</collectionViewFlowLayout>
|
||||
<cells>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AssetCell" id="hn9-bM-eId" customClass="AssetCell" customModule="NohanaImagePicker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="110" width="78" height="78"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="78" height="78"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="TB3-Xf-nik">
|
||||
<rect key="frame" x="0.0" y="0.0" width="78" height="78"/>
|
||||
</imageView>
|
||||
<view hidden="YES" alpha="0.30000001192092896" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="SnZ-bd-Zia">
|
||||
<rect key="frame" x="0.0" y="0.0" width="78" height="78"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vrt-tc-b54">
|
||||
<rect key="frame" x="34" y="0.0" width="44" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="44" id="BX8-gP-86t"/>
|
||||
<constraint firstAttribute="height" constant="44" id="RUG-gG-ieX"/>
|
||||
</constraints>
|
||||
<state key="normal" image="btn_select_m"/>
|
||||
<connections>
|
||||
<action selector="didPushPickButton:" destination="hn9-bM-eId" eventType="touchUpInside" id="g70-dv-o5C"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="SnZ-bd-Zia" secondAttribute="bottom" constant="-8" id="1hA-eS-4fw"/>
|
||||
<constraint firstItem="SnZ-bd-Zia" firstAttribute="leading" secondItem="hn9-bM-eId" secondAttribute="leadingMargin" constant="-8" id="57F-oY-ykD"/>
|
||||
<constraint firstItem="vrt-tc-b54" firstAttribute="top" secondItem="hn9-bM-eId" secondAttribute="topMargin" constant="-8" id="Djb-rK-T7y"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="vrt-tc-b54" secondAttribute="trailing" constant="-8" id="KEs-ry-rwP"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="TB3-Xf-nik" secondAttribute="trailing" constant="-8" id="XM8-uU-hsZ"/>
|
||||
<constraint firstItem="TB3-Xf-nik" firstAttribute="top" secondItem="hn9-bM-eId" secondAttribute="topMargin" constant="-8" id="avn-LP-mMH"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="TB3-Xf-nik" secondAttribute="bottom" constant="-8" id="bvb-eR-krl"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="SnZ-bd-Zia" secondAttribute="trailing" constant="-8" id="kX3-02-UOR"/>
|
||||
<constraint firstItem="SnZ-bd-Zia" firstAttribute="top" secondItem="hn9-bM-eId" secondAttribute="topMargin" constant="-8" id="vZV-H0-2Fs"/>
|
||||
<constraint firstItem="TB3-Xf-nik" firstAttribute="leading" secondItem="hn9-bM-eId" secondAttribute="leadingMargin" constant="-8" id="wGD-kd-Ibg"/>
|
||||
</constraints>
|
||||
<size key="customSize" width="78" height="78"/>
|
||||
<connections>
|
||||
<outlet property="imageView" destination="TB3-Xf-nik" id="HVf-Zj-nzV"/>
|
||||
<outlet property="overlayView" destination="SnZ-bd-Zia" id="27X-Fy-OP9"/>
|
||||
<outlet property="pickButton" destination="vrt-tc-b54" id="MVQ-KJ-OAp"/>
|
||||
<segue destination="r7t-t8-AuE" kind="show" id="Bed-w3-B1Q"/>
|
||||
</connections>
|
||||
</collectionViewCell>
|
||||
</cells>
|
||||
<collectionReusableView key="sectionHeaderView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MomentHeader" id="BCa-t3-9XW" customClass="MomentSectionHeaderView" customModule="NohanaImagePicker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Date" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aNJ-Oh-VhZ">
|
||||
<rect key="frame" x="12" y="11" width="120" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="21" id="KSm-hH-VZX"/>
|
||||
<constraint firstAttribute="width" constant="120" id="QzC-0j-DZA"/>
|
||||
<constraint firstAttribute="height" constant="21" id="XMh-5E-eAL"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="KSm-hH-VZX"/>
|
||||
</mask>
|
||||
</variation>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9Aa-PA-AHS">
|
||||
<rect key="frame" x="132" y="12" width="176" height="20.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="21" id="QVr-qn-Rz7"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="aNJ-Oh-VhZ" firstAttribute="centerY" secondItem="BCa-t3-9XW" secondAttribute="centerY" id="MyW-U2-vOY"/>
|
||||
<constraint firstItem="9Aa-PA-AHS" firstAttribute="trailing" secondItem="BCa-t3-9XW" secondAttribute="trailingMargin" constant="-4" id="Ufe-hG-OzN"/>
|
||||
<constraint firstItem="aNJ-Oh-VhZ" firstAttribute="leading" secondItem="BCa-t3-9XW" secondAttribute="leadingMargin" constant="4" id="Ws5-lF-5jV"/>
|
||||
<constraint firstItem="aNJ-Oh-VhZ" firstAttribute="leading" secondItem="BCa-t3-9XW" secondAttribute="leadingMargin" id="X0t-BQ-hqg"/>
|
||||
<constraint firstItem="aNJ-Oh-VhZ" firstAttribute="centerY" secondItem="BCa-t3-9XW" secondAttribute="centerY" id="XbD-RN-36L"/>
|
||||
<constraint firstItem="9Aa-PA-AHS" firstAttribute="centerY" secondItem="BCa-t3-9XW" secondAttribute="centerY" id="uN3-IU-mxA"/>
|
||||
<constraint firstItem="9Aa-PA-AHS" firstAttribute="leading" secondItem="aNJ-Oh-VhZ" secondAttribute="trailing" id="zWA-MS-zg7"/>
|
||||
</constraints>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="X0t-BQ-hqg"/>
|
||||
<exclude reference="XbD-RN-36L"/>
|
||||
</mask>
|
||||
</variation>
|
||||
<connections>
|
||||
<outlet property="dateLabel" destination="aNJ-Oh-VhZ" id="Zr4-vz-aX3"/>
|
||||
<outlet property="locationLabel" destination="9Aa-PA-AHS" id="fn1-wx-XK0"/>
|
||||
</connections>
|
||||
</collectionReusableView>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="FOz-K3-QuR" id="wch-Jd-Ads"/>
|
||||
<outlet property="delegate" destination="FOz-K3-QuR" id="zvh-co-HCR"/>
|
||||
</connections>
|
||||
</collectionView>
|
||||
<navigationItem key="navigationItem" id="Fcb-Wq-WEM">
|
||||
<barButtonItem key="rightBarButtonItem" systemItem="done" id="Tfy-aE-Xjc">
|
||||
<connections>
|
||||
<action selector="didPushDone:" destination="FOz-K3-QuR" id="mHU-vd-pbC"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<size key="freeformSize" width="320" height="568"/>
|
||||
</collectionViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="A16-1a-z3b" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1156" y="914"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="btn_select_l" width="28" height="28"/>
|
||||
<image name="btn_select_m" width="44" height="44"/>
|
||||
</resources>
|
||||
<inferredMetricsTieBreakers>
|
||||
<segue reference="Bed-w3-B1Q"/>
|
||||
</inferredMetricsTieBreakers>
|
||||
</document>
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
//
|
||||
// NohanaImagePickerController.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/09.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Photos
|
||||
|
||||
public enum MediaType: Int {
|
||||
case Any = 0, Photo, Video
|
||||
}
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
@objc public protocol NohanaImagePickerControllerDelegate {
|
||||
func nohanaImagePickerDidCancel(picker: NohanaImagePickerController)
|
||||
func nohanaImagePicker(picker: NohanaImagePickerController, didFinishPickingPhotoKitAssets pickedAssts :[PHAsset])
|
||||
optional func nohanaImagePicker(picker: NohanaImagePickerController, willPickPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int) -> Bool
|
||||
optional func nohanaImagePicker(picker: NohanaImagePickerController, didPickPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int)
|
||||
optional func nohanaImagePicker(picker: NohanaImagePickerController, willDropPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int) -> Bool
|
||||
optional func nohanaImagePicker(picker: NohanaImagePickerController, didDropPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int)
|
||||
optional func nohanaImagePicker(picker: NohanaImagePickerController, didSelectPhotoKitAsset asset: PHAsset)
|
||||
optional func nohanaImagePicker(picker: NohanaImagePickerController, didSelectPhotoKitAssetList assetList: PHAssetCollection)
|
||||
optional func nohanaImagePickerDidSelectMoment(picker: NohanaImagePickerController) -> Void
|
||||
optional func nohanaImagePicker(picker: NohanaImagePickerController, assetListViewController: UICollectionViewController, cell: UICollectionViewCell, indexPath: NSIndexPath, photoKitAsset: PHAsset) -> UICollectionViewCell
|
||||
optional func nohanaImagePicker(picker: NohanaImagePickerController, assetDetailListViewController: UICollectionViewController, cell: UICollectionViewCell, indexPath: NSIndexPath, photoKitAsset: PHAsset) -> UICollectionViewCell
|
||||
optional func nohanaImagePicker(picker: NohanaImagePickerController, assetDetailListViewController: UICollectionViewController, didChangeAssetDetailPage indexPath: NSIndexPath, photoKitAsset: PHAsset)
|
||||
|
||||
}
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
public class NohanaImagePickerController: UIViewController {
|
||||
|
||||
public var maximumNumberOfSelection: Int = 21 // set 0 to set no limit
|
||||
public var numberOfColumnsInPortrait: Int = 4
|
||||
public var numberOfColumnsInLandscape: Int = 7
|
||||
public weak var delegate: NohanaImagePickerControllerDelegate?
|
||||
public var shouldShowMoment: Bool = true
|
||||
public var shouldShowEmptyAlbum: Bool = false
|
||||
public var toolbarHidden: Bool = false
|
||||
public var canPickAsset = { (asset:AssetType) -> Bool in
|
||||
return true
|
||||
}
|
||||
lazy var assetBundle:NSBundle = NSBundle(forClass: self.dynamicType)
|
||||
let pickedAssetList: PickedAssetList
|
||||
let mediaType: MediaType
|
||||
private let assetCollectionSubtypes: [PHAssetCollectionSubtype]
|
||||
|
||||
public init() {
|
||||
assetCollectionSubtypes = [
|
||||
.AlbumRegular,
|
||||
.AlbumSyncedEvent,
|
||||
.AlbumSyncedFaces,
|
||||
.AlbumSyncedAlbum,
|
||||
.AlbumImported,
|
||||
.AlbumMyPhotoStream,
|
||||
.AlbumCloudShared,
|
||||
.SmartAlbumGeneric,
|
||||
.SmartAlbumFavorites,
|
||||
.SmartAlbumRecentlyAdded,
|
||||
.SmartAlbumUserLibrary
|
||||
]
|
||||
mediaType = .Photo
|
||||
pickedAssetList = PickedAssetList()
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
self.pickedAssetList.nohanaImagePickerController = self
|
||||
}
|
||||
|
||||
public init(assetCollectionSubtypes: [PHAssetCollectionSubtype], mediaType: MediaType) {
|
||||
self.assetCollectionSubtypes = assetCollectionSubtypes
|
||||
self.mediaType = mediaType
|
||||
pickedAssetList = PickedAssetList()
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
self.pickedAssetList.nohanaImagePickerController = self
|
||||
}
|
||||
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override public func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// show albumListViewController
|
||||
let storyboard = UIStoryboard(name: "NohanaImagePicker", bundle: assetBundle)
|
||||
guard let navigationController = storyboard.instantiateInitialViewController() as? UINavigationController else {
|
||||
fatalError("navigationController init failed.")
|
||||
}
|
||||
addChildViewController(navigationController)
|
||||
view.addSubview(navigationController.view)
|
||||
navigationController.didMoveToParentViewController(self)
|
||||
|
||||
// setup albumListViewController
|
||||
guard let albumListViewController = navigationController.topViewController as? AlbumListViewController else {
|
||||
fatalError("albumListViewController is not topViewController.")
|
||||
}
|
||||
albumListViewController.photoKitAlbumList =
|
||||
PhotoKitAlbumList(
|
||||
assetCollectionTypes: [.SmartAlbum, .Album],
|
||||
assetCollectionSubtypes: assetCollectionSubtypes,
|
||||
mediaType: mediaType,
|
||||
shouldShowEmptyAlbum: shouldShowEmptyAlbum,
|
||||
handler: {
|
||||
dispatch_async(dispatch_get_main_queue(), { () -> Void in
|
||||
albumListViewController.isLoading = false
|
||||
albumListViewController.tableView.reloadData()
|
||||
})
|
||||
})
|
||||
albumListViewController.nohanaImagePickerController = self
|
||||
}
|
||||
|
||||
public func pickAsset(asset: AssetType) {
|
||||
pickedAssetList.pickAsset(asset)
|
||||
}
|
||||
|
||||
public func dropAsset(asset: AssetType) {
|
||||
pickedAssetList.dropAsset(asset)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// NotificationInfo.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/19.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
struct NotificationInfo {
|
||||
struct Asset {
|
||||
struct PhotoKit {
|
||||
static let didPick = "jp.co.nohana.NotificationName.Asset.PhotoKit.didPick"
|
||||
static let didPickUserInfoKeyAsset = "asset"
|
||||
static let didPickUserInfoKeyPickedAssetsCount = "pickedAssetsCount"
|
||||
static let didDrop = "jp.co.nohana.NotificationName.Asset.PhotoKit.didDrop"
|
||||
static let didDropUserInfoKeyAsset = "asset"
|
||||
static let didDropUserInfoKeyPickedAssetsCount = "pickedAssetsCount"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
//
|
||||
// PhotoKitAlbumList.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/10.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import Photos
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
public class PhotoKitAlbumList: ItemListType {
|
||||
|
||||
private var albumList:[Item] = []
|
||||
private let assetCollectionTypes: [PHAssetCollectionType]
|
||||
private let assetCollectionSubtypes: [PHAssetCollectionSubtype]
|
||||
private let mediaType: MediaType
|
||||
private var shouldShowEmptyAlbum: Bool
|
||||
|
||||
// MARK: - init
|
||||
|
||||
init(assetCollectionTypes: [PHAssetCollectionType], assetCollectionSubtypes: [PHAssetCollectionSubtype], mediaType: MediaType, shouldShowEmptyAlbum: Bool, handler:(() -> Void)?) {
|
||||
self.assetCollectionTypes = assetCollectionTypes
|
||||
self.assetCollectionSubtypes = assetCollectionSubtypes
|
||||
self.mediaType = mediaType
|
||||
self.shouldShowEmptyAlbum = shouldShowEmptyAlbum
|
||||
update { () -> Void in
|
||||
if let handler = handler {
|
||||
handler()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ItemListType
|
||||
|
||||
public typealias Item = PhotoKitAssetList
|
||||
|
||||
public var title:String {
|
||||
get {
|
||||
return "PhotoKit"
|
||||
}
|
||||
}
|
||||
|
||||
public func update(handler:(() -> Void)?) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { () -> Void in
|
||||
var albumListFetchResult: [PHFetchResult] = []
|
||||
for type in self.assetCollectionTypes {
|
||||
albumListFetchResult = albumListFetchResult + [PHAssetCollection.fetchAssetCollectionsWithType(type, subtype: .Any, options: nil)]
|
||||
}
|
||||
|
||||
self.albumList = []
|
||||
var tmpAlbumList:[Item] = []
|
||||
let isAssetCollectionSubtypeAny = self.assetCollectionSubtypes.contains(.Any)
|
||||
for fetchResult in albumListFetchResult {
|
||||
fetchResult.enumerateObjectsUsingBlock { (album, index, stop) -> Void in
|
||||
guard let album = album as? PHAssetCollection else {
|
||||
return
|
||||
}
|
||||
if self.assetCollectionSubtypes.contains(album.assetCollectionSubtype) || isAssetCollectionSubtypeAny {
|
||||
if self.shouldShowEmptyAlbum || PHAsset.fetchAssetsInAssetCollection(album, options: PhotoKitAssetList.fetchOptions(self.mediaType)).count != 0 {
|
||||
tmpAlbumList.append(PhotoKitAssetList(album: album, mediaType: self.mediaType))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.assetCollectionTypes == [.Moment] {
|
||||
self.albumList = tmpAlbumList.sort{ $0.date?.timeIntervalSince1970 < $1.date?.timeIntervalSince1970 }
|
||||
} else {
|
||||
self.albumList = tmpAlbumList
|
||||
}
|
||||
|
||||
if let handler = handler {
|
||||
handler()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public subscript (index: Int) -> Item {
|
||||
get {
|
||||
return albumList[index] as Item
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CollectionType
|
||||
|
||||
public var startIndex: Int {
|
||||
get {
|
||||
return albumList.startIndex
|
||||
}
|
||||
}
|
||||
|
||||
public var endIndex: Int {
|
||||
get {
|
||||
return albumList.endIndex
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// PhotoKitAsset.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/11.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import Photos
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
public class PhotoKitAsset :AssetType {
|
||||
|
||||
let asset: PHAsset
|
||||
|
||||
public init(asset: PHAsset) {
|
||||
self.asset = asset
|
||||
}
|
||||
|
||||
public var originalAsset: PHAsset {
|
||||
get {
|
||||
return asset as PHAsset
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - AssetType
|
||||
|
||||
public var identifier:Int {
|
||||
get {
|
||||
return asset.localIdentifier.hash
|
||||
}
|
||||
}
|
||||
|
||||
public func image(targetSize:CGSize, handler: (ImageData?) -> Void) {
|
||||
let option = PHImageRequestOptions()
|
||||
option.networkAccessAllowed = true
|
||||
|
||||
PHImageManager.defaultManager().requestImageForAsset(
|
||||
self.asset,
|
||||
targetSize: targetSize,
|
||||
contentMode: .AspectFit,
|
||||
options: option ) { (image, info) -> Void in
|
||||
guard let image = image else {
|
||||
handler(nil)
|
||||
return
|
||||
}
|
||||
handler(ImageData(image: image, info: info))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
//
|
||||
// PhotoKitAssetList.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/11.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
import Photos
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
public class PhotoKitAssetList :ItemListType {
|
||||
|
||||
private let mediaType: MediaType
|
||||
public let assetList: PHAssetCollection
|
||||
private var fetchResult: PHFetchResult!
|
||||
|
||||
init(album: PHAssetCollection, mediaType: MediaType) {
|
||||
self.assetList = album
|
||||
self.mediaType = mediaType
|
||||
update()
|
||||
}
|
||||
|
||||
// MARK: - ItemListType
|
||||
|
||||
public typealias Item = PhotoKitAsset
|
||||
|
||||
public var title: String {
|
||||
get{
|
||||
return assetList.localizedTitle ?? ""
|
||||
}
|
||||
}
|
||||
|
||||
public var date: NSDate? {
|
||||
get {
|
||||
return assetList.startDate
|
||||
}
|
||||
}
|
||||
|
||||
class func fetchOptions(mediaType: MediaType) -> PHFetchOptions {
|
||||
let options = PHFetchOptions()
|
||||
switch mediaType {
|
||||
case .Photo:
|
||||
options.predicate = NSPredicate(format: "mediaType == %ld", PHAssetMediaType.Image.rawValue)
|
||||
default:
|
||||
fatalError("not supported .Video and .Any yet")
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
public func update(handler: (() -> Void)? = nil) {
|
||||
fetchResult = PHAsset.fetchAssetsInAssetCollection(assetList, options: PhotoKitAssetList.fetchOptions(mediaType))
|
||||
if let handler = handler {
|
||||
handler()
|
||||
}
|
||||
}
|
||||
|
||||
public subscript (index: Int) -> Item {
|
||||
get {
|
||||
guard let asset = fetchResult[index] as? PHAsset else {
|
||||
fatalError("invalid index")
|
||||
}
|
||||
return Item(asset: asset)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CollectionType
|
||||
|
||||
public var startIndex: Int {
|
||||
get {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
public var endIndex: Int {
|
||||
get {
|
||||
return fetchResult.count
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
//
|
||||
// PickedAssetList.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/17.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
class PickedAssetList: ItemListType {
|
||||
|
||||
var assetlist: Array<AssetType> = []
|
||||
weak var nohanaImagePickerController: NohanaImagePickerController?
|
||||
|
||||
// MARK: - ItemListType
|
||||
|
||||
typealias Item = AssetType
|
||||
|
||||
var title: String {
|
||||
get {
|
||||
return "Selected Assets"
|
||||
}
|
||||
}
|
||||
|
||||
func update(handler:(() -> Void)?) {
|
||||
fatalError("not supported")
|
||||
}
|
||||
|
||||
|
||||
subscript (index: Int) -> Item {
|
||||
get {
|
||||
return assetlist[index]
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CollectionType
|
||||
|
||||
var startIndex: Int {
|
||||
get {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
var endIndex: Int {
|
||||
get {
|
||||
return assetlist.count
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Manage assetlist
|
||||
|
||||
func pickAsset(asset: AssetType) -> Bool {
|
||||
guard !isPicked(asset) else {
|
||||
return false
|
||||
}
|
||||
guard let nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return false
|
||||
}
|
||||
let assetsCountBeforePicking = self.count
|
||||
if asset is PhotoKitAsset {
|
||||
if let canPick = nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, willPickPhotoKitAsset: (asset as! PhotoKitAsset).originalAsset, pickedAssetsCount: assetsCountBeforePicking)
|
||||
where !canPick {
|
||||
return false
|
||||
}
|
||||
}
|
||||
guard nohanaImagePickerController.maximumNumberOfSelection == 0 || assetsCountBeforePicking < nohanaImagePickerController.maximumNumberOfSelection else {
|
||||
return false
|
||||
}
|
||||
assetlist.append(asset)
|
||||
let assetsCountAfterPicking = self.count
|
||||
if asset is PhotoKitAsset {
|
||||
let originalAsset = (asset as! PhotoKitAsset).originalAsset
|
||||
nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, didPickPhotoKitAsset: originalAsset, pickedAssetsCount: assetsCountAfterPicking)
|
||||
NSNotificationCenter.defaultCenter().postNotification(
|
||||
NSNotification(
|
||||
name: NotificationInfo.Asset.PhotoKit.didPick,
|
||||
object: nohanaImagePickerController,
|
||||
userInfo: [
|
||||
NotificationInfo.Asset.PhotoKit.didPickUserInfoKeyAsset : originalAsset,
|
||||
NotificationInfo.Asset.PhotoKit.didPickUserInfoKeyPickedAssetsCount : assetsCountAfterPicking
|
||||
]
|
||||
)
|
||||
)
|
||||
}
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
func dropAsset(asset: AssetType) -> Bool {
|
||||
guard let nohanaImagePickerController = nohanaImagePickerController else {
|
||||
return false
|
||||
}
|
||||
let assetsCountBeforeDropping = self.count
|
||||
if asset is PhotoKitAsset {
|
||||
if let canDrop = nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, willDropPhotoKitAsset: (asset as! PhotoKitAsset).originalAsset, pickedAssetsCount: assetsCountBeforeDropping) where !canDrop {
|
||||
return false
|
||||
}
|
||||
}
|
||||
assetlist = assetlist.filter{ $0.identifier != asset.identifier }
|
||||
let assetsCountAfterDropping = self.count
|
||||
if asset is PhotoKitAsset {
|
||||
let originalAsset = (asset as! PhotoKitAsset).originalAsset
|
||||
nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, didDropPhotoKitAsset: originalAsset, pickedAssetsCount: assetsCountAfterDropping)
|
||||
NSNotificationCenter.defaultCenter().postNotification(
|
||||
NSNotification(
|
||||
name: NotificationInfo.Asset.PhotoKit.didDrop,
|
||||
object: nohanaImagePickerController,
|
||||
userInfo: [
|
||||
NotificationInfo.Asset.PhotoKit.didDropUserInfoKeyAsset : originalAsset,
|
||||
NotificationInfo.Asset.PhotoKit.didDropUserInfoKeyPickedAssetsCount : assetsCountAfterDropping
|
||||
]
|
||||
)
|
||||
)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isPicked(asset: AssetType) -> Bool {
|
||||
return assetlist.contains{ $0.identifier == asset.identifier }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// Size.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/14.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
struct Size {
|
||||
|
||||
static let statusBarHeight = UIApplication.sharedApplication().statusBarFrame.size.height
|
||||
|
||||
static func navigationBarHeight(viewController: UIViewController) -> CGFloat {
|
||||
return viewController.navigationController?.navigationBar.frame.size.height ?? CGFloat(44)
|
||||
}
|
||||
|
||||
static func appBarHeight(viewController: UIViewController) -> CGFloat {
|
||||
return statusBarHeight + navigationBarHeight(viewController)
|
||||
}
|
||||
|
||||
static func toolbarHeight(viewController: UIViewController) -> CGFloat {
|
||||
guard let navigationController = viewController.navigationController else {
|
||||
return 0
|
||||
}
|
||||
guard !navigationController.toolbarHidden else {
|
||||
return 0
|
||||
}
|
||||
return navigationController.toolbar.frame.size.height
|
||||
}
|
||||
|
||||
static func screenRectWithoutAppBar(viewController: UIViewController) -> CGRect {
|
||||
let appBarHeight = Size.appBarHeight(viewController)
|
||||
let toolbarHeight = Size.toolbarHeight(viewController)
|
||||
return CGRect(
|
||||
x: 0,
|
||||
y: appBarHeight,
|
||||
width: UIScreen.mainScreen().bounds.width,
|
||||
height: UIScreen.mainScreen().bounds.height - appBarHeight - toolbarHeight)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// SwipeInteractionController.swift
|
||||
// NohanaImagePicker
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/21.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@available(iOS 8.0, *)
|
||||
class SwipeInteractionController: UIPercentDrivenInteractiveTransition {
|
||||
|
||||
var viewController: UIViewController?
|
||||
|
||||
func attachToViewController(viewController: UIViewController) {
|
||||
guard viewController.navigationController?.viewControllers.count > 1 else {
|
||||
return
|
||||
}
|
||||
let target = viewController.navigationController?.valueForKey("_cachedInteractionController")
|
||||
let gesture = UIScreenEdgePanGestureRecognizer(target: target, action: "handleNavigationTransition:")
|
||||
gesture.edges = .Left
|
||||
viewController.view.addGestureRecognizer(gesture)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
NohanaImagePicker.strings
|
||||
NohanaImagePicker
|
||||
|
||||
Created by kazushi.hara on 2016/02/15.
|
||||
Copyright © 2016年 nohana. All rights reserved.
|
||||
*/
|
||||
|
||||
"albumlist.title" = "Photos";
|
||||
"albumlist.empty.message" = "No Photos";
|
||||
"albumlist.empty.description" = "Take some photos with Camera app.";
|
||||
"albumlist.moment.title" = "Moment";
|
||||
"toolbar.title.nolimit" = "Selected Items: %ld";
|
||||
"toolbar.title.haslimit" = "Selected Items: %ld / %ld";
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
NohanaImagePicker.strings
|
||||
NohanaImagePicker
|
||||
|
||||
Created by kazushi.hara on 2016/02/15.
|
||||
Copyright © 2016年 nohana. All rights reserved.
|
||||
*/
|
||||
|
||||
"albumlist.title" = "アルバム";
|
||||
"albumlist.empty.message" = "アルバムに\n写真がありません";
|
||||
"albumlist.empty.description" = "カメラで写真を撮影しましょう";
|
||||
"albumlist.moment.title" = "日付から選択";
|
||||
"toolbar.title.nolimit" = "%ld枚選択中";
|
||||
"toolbar.title.haslimit" = "%ld枚選択中(最大%ld枚)";
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// AppDelegate.swift
|
||||
// NohanaImagePickerSample
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/08.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
|
||||
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
func applicationWillResignActive(application: UIApplication) {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
func applicationDidEnterBackground(application: UIApplication) {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
func applicationWillEnterForeground(application: UIApplication) {
|
||||
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(application: UIApplication) {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
func applicationWillTerminate(application: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "83.5x83.5",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8150" systemVersion="15A204g" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8122"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<animations/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9532" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9530"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="NohanaImagePickerSample" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// ViewController.swift
|
||||
// NohanaImagePickerSample
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/08.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Photos
|
||||
import NohanaImagePicker
|
||||
|
||||
class ViewController: UIViewController, NohanaImagePickerControllerDelegate {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
}
|
||||
|
||||
override func viewDidAppear(animated: Bool) {
|
||||
let picker = NohanaImagePickerController()
|
||||
picker.delegate = self
|
||||
picker.maximumNumberOfSelection = 4
|
||||
picker.canPickAsset = { (asset:AssetType) -> Bool in
|
||||
return asset.identifier % 10 != 0
|
||||
}
|
||||
presentViewController(picker, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
override func didReceiveMemoryWarning() {
|
||||
super.didReceiveMemoryWarning()
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
// MARK: - NohanaImagePickerControllerDelegate
|
||||
|
||||
func nohanaImagePickerDidCancel(picker: NohanaImagePickerController) {
|
||||
picker.dismissViewControllerAnimated(true, completion: nil)
|
||||
}
|
||||
|
||||
func nohanaImagePicker(picker: NohanaImagePickerController, didFinishPickingPhotoKitAssets pickedAssts :[PHAsset]) {
|
||||
picker.dismissViewControllerAnimated(true, completion: nil)
|
||||
}
|
||||
|
||||
func willPickPhotoKitAsset(asset: PHAsset, pickedAssetsCount: Int) -> Bool {
|
||||
print("func:\(__FUNCTION__), asset: \(asset), pickedAssetsCount: \(pickedAssetsCount)")
|
||||
return true
|
||||
}
|
||||
|
||||
func didPickPhotoKitAsset(asset: PHAsset, pickedAssetsCount: Int) {
|
||||
print("func:\(__FUNCTION__), asset: \(asset), pickedAssetsCount: \(pickedAssetsCount)")
|
||||
}
|
||||
|
||||
func willDropPhotoKitAsset(asset: PHAsset, pickedAssetsCount: Int) -> Bool {
|
||||
print("func:\(__FUNCTION__), asset: \(asset), pickedAssetsCount: \(pickedAssetsCount)")
|
||||
return true
|
||||
}
|
||||
|
||||
func didDropPhotoKitAsset(asset: PHAsset, pickedAssetsCount: Int) {
|
||||
print("func:\(__FUNCTION__), asset: \(asset), pickedAssetsCount: \(pickedAssetsCount)")
|
||||
}
|
||||
|
||||
func didSelectPhotoKitAsset(asset: PHAsset) {
|
||||
print("func:\(__FUNCTION__), assetList: \(asset)")
|
||||
}
|
||||
|
||||
func didSelectPhotoKitAssetList(assetList: PHAssetCollection) {
|
||||
print("func:\(__FUNCTION__), assetList: \(assetList)")
|
||||
}
|
||||
|
||||
func assetListView(collectionView: UICollectionView, cell: UICollectionViewCell, indexPath: NSIndexPath, photoKitAsset: PHAsset) -> UICollectionViewCell {
|
||||
print("func:\(__FUNCTION__), cell:\(cell), indexPath: \(indexPath), photoKitAsset: \(photoKitAsset)")
|
||||
return cell
|
||||
}
|
||||
|
||||
func assetDetailListView(collectionView: UICollectionView, cell: UICollectionViewCell, indexPath: NSIndexPath, photoKitAsset: PHAsset) -> UICollectionViewCell {
|
||||
print("func:\(__FUNCTION__), cell:\(cell), indexPath: \(indexPath), photoKitAsset: \(photoKitAsset)")
|
||||
return cell
|
||||
}
|
||||
|
||||
func didChangeAssetDetailPage(indexPath: NSIndexPath, photoKitAsset: PHAsset) {
|
||||
print("func:\(__FUNCTION__), indexPath: \(indexPath), photoKitAsset: \(photoKitAsset)")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// NohanaImagePickerSampleTests.swift
|
||||
// NohanaImagePickerSampleTests
|
||||
//
|
||||
// Created by kazushi.hara on 2016/02/08.
|
||||
// Copyright © 2016年 nohana. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import NohanaImagePickerSample
|
||||
|
||||
class NohanaImagePickerSampleTests: XCTestCase {
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testExample() {
|
||||
// This is an example of a functional test case.
|
||||
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
||||
}
|
||||
|
||||
func testPerformanceExample() {
|
||||
// This is an example of a performance test case.
|
||||
self.measureBlock {
|
||||
// Put the code you want to measure the time of here.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||