Compare commits

..

9 Commits

Author SHA1 Message Date
Kazushi Hara a10b65a739 Merge pull request #58 from nohana/update-recommended-project-settings
update project settings
2016-09-26 15:22:42 +09:00
haranicle 52bbdb08a7 update project settings 2016-09-26 15:22:06 +09:00
Kazushi Hara dba26e08f7 Merge pull request #57 from nohana/fix-build-animation
fix build error
2016-09-26 15:20:32 +09:00
haranicle fb874ac8a7 fix build error 2016-09-26 15:19:47 +09:00
Kazushi Hara c87637346f Merge pull request #56 from nohana/release/0.6.1
Release/0.6.1
2016-09-26 15:02:04 +09:00
Kazushi Hara 6c3911f6a7 Merge pull request #55 from nohana/add-swift-version-file
add swift version file
2016-09-26 14:59:51 +09:00
haranicle 4b3d2a40f8 add swift version file 2016-09-26 14:57:56 +09:00
Kazushi Hara 985be6cf63 Merge pull request #54 from nohana/fix-project-settings
fix project setting for Xcode8
2016-09-26 14:54:05 +09:00
haranicle 0f9f827bc6 fix project setting for Xcode8 2016-09-26 14:52:29 +09:00
61 changed files with 930 additions and 1060 deletions

View File

@ -1 +1,2 @@
4.2
2.3

View File

@ -1,47 +0,0 @@
disabled_rules: # rule identifiers to exclude from running
- todo
# - colon
# - comma
# - control_statement
- file_length
- force_cast
- force_try
- function_body_length
# - leading_whitespace
- line_length
- legacy_constructor
- nesting
# - opening_brace
# - operator_whitespace
# - return_arrow_whitespace
# - statement_position
# - todo
# - trailing_newline
# - trailing_semicolon
# - trailing_whitespace
- type_body_length
- type_name
- variable_name_max_length
- variable_name_min_length
- variable_name
- valid_docs
- function_parameter_count
- cyclomatic_complexity
excluded: # paths to ignore during linting.
- Carthage
- Pods
- .git
# parameterized rules can be customized from this configuration file
line_length: 300 # default 100
type_body_length:
- 200 # warning default 200
- 650 # error default 350
function_body_length:
- 80 # warning default 40
- 250 # error default 100
file_length:
- 400 # warning default 400
- 1300 # error default 1000
variable_name_min_length:
- 1 # warning default 3
- 0 # error default 2

View File

@ -22,32 +22,33 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(_ application: UIApplication) {
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) {
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) {
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) {
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) {
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}

View File

@ -1,15 +1,5 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
@ -42,16 +32,6 @@
"filename" : "180.png",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
@ -89,11 +69,6 @@
"idiom" : "ipad",
"filename" : "167.png",
"scale" : "2x"
},
{
"idiom" : "ios-marketing",
"size" : "1024x1024",
"scale" : "1x"
}
],
"info" : {

View File

@ -1,12 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="q5W-GZ-eHb">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<?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="q5W-GZ-eHb">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13173"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9530"/>
</dependencies>
<scenes>
<!--NohanaImagePicker-->
@ -14,22 +10,22 @@
<objects>
<tableViewController id="G3T-A5-GIu" customClass="DemoListViewController" customModule="Demo" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="LNK-dE-8Ye">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" textLabel="lwK-uA-3Me" style="IBUITableViewCellStyleDefault" id="6f6-ob-xNw">
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
<rect key="frame" x="0.0" y="92" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="6f6-ob-xNw" id="VH4-Rk-3Uo">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="lwK-uA-3Me">
<rect key="frame" x="16" y="0.0" width="344" height="43.5"/>
<rect key="frame" x="15" y="0.0" width="570" height="43.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@ -53,7 +49,7 @@
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="q5W-GZ-eHb" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="RTV-gX-iYb">
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>

View File

@ -23,172 +23,159 @@ struct Cell {
}
class DemoListViewController: UITableViewController, NohanaImagePickerControllerDelegate {
let cells = [
Cell(title: "Default", selector: #selector(DemoListViewController.showDefaultPicker)),
Cell(title: "Large thumbnail", selector: #selector(DemoListViewController.showLargeThumbnailPicker)),
Cell(title: "No toolbar", selector: #selector(DemoListViewController.showNoToolbarPicker)),
Cell(title: "Disable to pick assets", selector: #selector(DemoListViewController.showDisableToPickAssetsPicker)),
Cell(title: "Custom UI", selector: #selector(DemoListViewController.showCustomUIPicker)),
]
override func viewDidAppear(_ animated: Bool) {
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if let indexPathForSelectedRow = tableView.indexPathForSelectedRow {
tableView.deselectRow(at: indexPathForSelectedRow, animated: true)
tableView.deselectRowAtIndexPath(indexPathForSelectedRow, animated: true)
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cells.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")!
cell.textLabel?.text = cells[indexPath.row].title
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
checkIfAuthorizedToAccessPhotos { isAuthorized in
DispatchQueue.main.async(execute: {
dispatch_async(dispatch_get_main_queue(), {
if isAuthorized {
self.perform(self.cells[indexPath.row].selector)
self.performSelector(self.cells[indexPath.row].selector)
} else {
let alert = UIAlertController(title: "Error", message: "Denied access to photos.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
let alert = UIAlertController(title: "Error", message: "Denied access to photos.", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
})
}
}
// MARK: - Photos
func checkIfAuthorizedToAccessPhotos(_ handler: @escaping (_ isAuthorized: Bool) -> Void) {
func checkIfAuthorizedToAccessPhotos(handler: (isAuthorized: Bool) -> Void) {
switch PHPhotoLibrary.authorizationStatus() {
case .notDetermined:
PHPhotoLibrary.requestAuthorization { status in
DispatchQueue.main.async {
switch status {
case .authorized:
handler(true)
default:
handler(false)
}
case .NotDetermined:
PHPhotoLibrary.requestAuthorization{ status in
switch status {
case .Authorized:
handler(isAuthorized: true)
default:
handler(isAuthorized: false)
}
}
case .restricted:
handler(false)
case .denied:
handler(false)
case .authorized:
handler(true)
default:
break
case .Restricted:
handler(isAuthorized: false)
case .Denied:
handler(isAuthorized: false)
case .Authorized:
handler(isAuthorized: true)
}
}
// MARK: - Show NohanaImagePicker
@objc func showDefaultPicker() {
@objc
func showDefaultPicker() {
let picker = NohanaImagePickerController()
picker.delegate = self
present(picker, animated: true, completion: nil)
presentViewController(picker, animated: true, completion: nil)
}
@objc func showLargeThumbnailPicker() {
@objc
func showLargeThumbnailPicker() {
let picker = NohanaImagePickerController()
picker.delegate = self
picker.numberOfColumnsInPortrait = 2
picker.numberOfColumnsInLandscape = 3
present(picker, animated: true, completion: nil)
presentViewController(picker, animated: true, completion: nil)
}
@objc func showNoToolbarPicker() {
@objc
func showNoToolbarPicker() {
let picker = NohanaImagePickerController()
picker.delegate = self
picker.toolbarHidden = true
present(picker, animated: true, completion: nil)
presentViewController(picker, animated: true, completion: nil)
}
@objc func showDisableToPickAssetsPicker() {
@objc
func showDisableToPickAssetsPicker() {
let picker = NohanaImagePickerController()
picker.delegate = self
picker.canPickAsset = { (asset: Asset) -> Bool in
picker.canPickAsset = { (asset:AssetType) -> Bool in
return asset.identifier % 2 == 0
}
present(picker, animated: true, completion: nil)
presentViewController(picker, animated: true, completion: nil)
}
@objc func showCustomUIPicker() {
let picker = NohanaImagePickerController()
picker.delegate = self
picker.config.color.background = UIColor(red: 0xcc/0xff, green: 0xff/0xff, blue: 0xff/0xff, alpha: 1)
picker.config.color.separator = UIColor(red: 0x00/0xff, green: 0x66/0xff, blue: 0x66/0xff, alpha: 1)
picker.config.strings.albumListTitle = "🏞"
picker.config.image.droppedSmall = UIImage(named: "btn_select_m")
picker.config.image.pickedSmall = UIImage(named: "btn_selected_m")
present(picker, animated: true, completion: nil)
}
// MARK: - NohanaImagePickerControllerDelegate
func nohanaImagePickerDidCancel(_ picker: NohanaImagePickerController) {
func nohanaImagePickerDidCancel(picker: NohanaImagePickerController) {
print("🐷Canceled🙅")
picker.dismiss(animated: true, completion: nil)
picker.dismissViewControllerAnimated(true, completion: nil)
}
func nohanaImagePicker(_ picker: NohanaImagePickerController, didFinishPickingPhotoKitAssets pickedAssts: [PHAsset]) {
func nohanaImagePicker(picker: NohanaImagePickerController, didFinishPickingPhotoKitAssets pickedAssts :[PHAsset]) {
print("🐷Completed🙆\n\tpickedAssets = \(pickedAssts)")
picker.dismiss(animated: true, completion: nil)
picker.dismissViewControllerAnimated(true, completion: nil)
}
func nohanaImagePicker(_ picker: NohanaImagePickerController, willPickPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int) -> Bool {
func nohanaImagePicker(picker: NohanaImagePickerController, willPickPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int) -> Bool {
print("🐷\(#function)\n\tasset = \(asset)\n\tpickedAssetsCount = \(pickedAssetsCount)")
return true
}
func nohanaImagePicker(_ picker: NohanaImagePickerController, didPickPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int) {
func nohanaImagePicker(picker: NohanaImagePickerController, didPickPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int) {
print("🐷\(#function)\n\tasset = \(asset)\n\tpickedAssetsCount = \(pickedAssetsCount)")
}
func nohanaImagePicker(_ picker: NohanaImagePickerController, willDropPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int) -> Bool {
func nohanaImagePicker(picker: NohanaImagePickerController, willDropPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int) -> Bool {
print("🐷\(#function)\n\tasset = \(asset)\n\tpickedAssetsCount = \(pickedAssetsCount)")
return true
}
func nohanaImagePicker(_ picker: NohanaImagePickerController, didDropPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int) {
func nohanaImagePicker(picker: NohanaImagePickerController, didDropPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int) {
print("🐷\(#function)\n\tasset = \(asset)\n\tpickedAssetsCount = \(pickedAssetsCount)")
}
func nohanaImagePicker(_ picker: NohanaImagePickerController, didSelectPhotoKitAsset asset: PHAsset) {
func nohanaImagePicker(picker: NohanaImagePickerController, didSelectPhotoKitAsset asset: PHAsset) {
print("🐷\(#function)\n\tasset = \(asset)\n\t")
}
func nohanaImagePicker(_ picker: NohanaImagePickerController, didSelectPhotoKitAssetList assetList: PHAssetCollection) {
func nohanaImagePicker(picker: NohanaImagePickerController, didSelectPhotoKitAssetList assetList: PHAssetCollection) {
print("🐷\(#function)\n\t\tassetList = \(assetList)\n\t")
}
func nohanaImagePickerDidSelectMoment(_ picker: NohanaImagePickerController) -> Void {
func nohanaImagePickerDidSelectMoment(picker: NohanaImagePickerController) -> Void {
print("🐷\(#function)")
}
func nohanaImagePicker(_ picker: NohanaImagePickerController, assetListViewController: UICollectionViewController, cell: UICollectionViewCell, indexPath: IndexPath, photoKitAsset: PHAsset) -> UICollectionViewCell {
func nohanaImagePicker(picker: NohanaImagePickerController, assetListViewController: UICollectionViewController, cell: UICollectionViewCell, indexPath: NSIndexPath, photoKitAsset: PHAsset) -> UICollectionViewCell {
print("🐷\(#function)\n\tindexPath = \(indexPath)\n\tphotoKitAsset = \(photoKitAsset)")
return cell
}
func nohanaImagePicker(_ picker: NohanaImagePickerController, assetDetailListViewController: UICollectionViewController, cell: UICollectionViewCell, indexPath: IndexPath, photoKitAsset: PHAsset) -> UICollectionViewCell {
func nohanaImagePicker(picker: NohanaImagePickerController, assetDetailListViewController: UICollectionViewController, cell: UICollectionViewCell, indexPath: NSIndexPath, photoKitAsset: PHAsset) -> UICollectionViewCell {
print("🐷\(#function)\n\tindexPath = \(indexPath)\n\tphotoKitAsset = \(photoKitAsset)")
return cell
}
func nohanaImagePicker(_ picker: NohanaImagePickerController, assetDetailListViewController: UICollectionViewController, didChangeAssetDetailPage indexPath: IndexPath, photoKitAsset: PHAsset) {
func nohanaImagePicker(picker: NohanaImagePickerController, assetDetailListViewController: UICollectionViewController, didChangeAssetDetailPage indexPath: NSIndexPath, photoKitAsset: PHAsset) {
print("🐷\(#function)\n\tindexPath = \(indexPath)")
}
}

View File

@ -43,7 +43,5 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSPhotoLibraryUsageDescription</key>
<string>To pick some photos.</string>
</dict>
</plist>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1,17 +1,15 @@
Pod::Spec.new do |s|
s.name = 'NohanaImagePicker'
s.version = '0.9.3'
s.summary = 'A multiple image picker for iOS app.'
s.homepage = 'https://github.com/TouchInstinct/NohanaImagePicker'
s.version = '0.6.0'
s.summary = 'Multiple image picker for iOS app.'
s.homepage = 'https://github.com/nohana/NohanaImagePicker'
s.license = { :type => 'Apache License v2', :file => 'LICENSE' }
s.author = { 'nohana' => 'development@nohana.co.jp' }
s.source = {
:git => 'https://github.com/TouchInstinct/NohanaImagePicker.git',
:tag => s.version.to_s }
s.source = { :git => 'https://github.com/nohana/NohanaImagePicker.git', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.source_files = 'NohanaImagePicker/*.swift'
s.resource_bundles = {
'NohanaImagePicker' => ['NohanaImagePicker/**/*.{xcassets,storyboard,lproj}', "Resources/NohanaImagePicker.storyboard"]
'NohanaImagePicker' => ['NohanaImagePicker/*.{xcassets,storyboard,lproj}']
}
s.frameworks = 'UIKit', 'Photos'
end
end

View File

@ -7,7 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
3569CAA91EC1918E000C41C0 /* NohanaImagePicker.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3569CAA61EC1918E000C41C0 /* NohanaImagePicker.xcassets */; };
F202573A1C7343D20069B33A /* ImageName.swift in Sources */ = {isa = PBXBuildFile; fileRef = F20257391C7343D20069B33A /* ImageName.swift */; };
F202573C1C7418920069B33A /* PickedAssetList.swift in Sources */ = {isa = PBXBuildFile; fileRef = F202573B1C7418920069B33A /* PickedAssetList.swift */; };
F208E5541CD7370B00FFC9F6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F208E5531CD7370B00FFC9F6 /* AppDelegate.swift */; };
F208E5591CD7370B00FFC9F6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F208E5571CD7370B00FFC9F6 /* Main.storyboard */; };
@ -21,14 +21,15 @@
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 /* NohanaImagePicker.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F237249A1C6DCF96005D1E8A /* NohanaImagePicker.xcassets */; };
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 */; };
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 */; };
F26775DE1C701FA7002E786C /* ItemList.swift in Sources */ = {isa = PBXBuildFile; fileRef = F26775DD1C701FA7002E786C /* ItemList.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 */; };
@ -70,9 +71,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
23D1CD93207CEB1200F8115E /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/NohanaImagePicker.strings; sourceTree = "<group>"; };
3569CAA61EC1918E000C41C0 /* NohanaImagePicker.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = NohanaImagePicker.xcassets; sourceTree = "<group>"; };
3590F1F51EC1A79400F32E06 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/NohanaImagePicker.strings; sourceTree = "<group>"; };
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>"; };
F208E5511CD7370B00FFC9F6 /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; };
F208E5531CD7370B00FFC9F6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@ -86,14 +85,15 @@
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 /* NohanaImagePicker.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = NohanaImagePicker.xcassets; 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>"; };
F26775DD1C701FA7002E786C /* ItemList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ItemList.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>"; };
@ -132,18 +132,9 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
3569CAA31EC1918E000C41C0 /* Resources */ = {
isa = PBXGroup;
children = (
3569CAA61EC1918E000C41C0 /* NohanaImagePicker.xcassets */,
);
path = Resources;
sourceTree = "<group>";
};
F208E5521CD7370B00FFC9F6 /* Demo */ = {
isa = PBXGroup;
children = (
3569CAA31EC1918E000C41C0 /* Resources */,
F208E5531CD7370B00FFC9F6 /* AppDelegate.swift */,
F208E5681CD738CD00FFC9F6 /* DemoListViewController.swift */,
F208E5571CD7370B00FFC9F6 /* Main.storyboard */,
@ -172,7 +163,7 @@
children = (
F23554251C69D19C00796DCA /* NohanaImagePicker.storyboard */,
F27029CD1C71C43A001647AB /* NohanaImagePicker.strings */,
F237249A1C6DCF96005D1E8A /* NohanaImagePicker.xcassets */,
F237249A1C6DCF96005D1E8A /* Images.xcassets */,
);
name = Resources;
sourceTree = "<group>";
@ -201,12 +192,14 @@
F26775E61C7073B1002E786C /* Common */ = {
isa = PBXGroup;
children = (
F26775DD1C701FA7002E786C /* ItemList.swift */,
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>";
@ -314,16 +307,14 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0720;
LastUpgradeCheck = 1000;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = nohana;
TargetAttributes = {
F208E5501CD7370B00FFC9F6 = {
CreatedOnToolsVersion = 7.2.1;
LastSwiftMigration = 0900;
};
F2C08D731C68651900B00181 = {
CreatedOnToolsVersion = 7.2.1;
LastSwiftMigration = 0900;
};
};
};
@ -335,8 +326,6 @@
en,
Base,
ja,
ru,
de,
);
mainGroup = F2C08D6A1C68651900B00181;
productRefGroup = F2C08D751C68651900B00181 /* Products */;
@ -355,7 +344,6 @@
buildActionMask = 2147483647;
files = (
F208E55E1CD7370B00FFC9F6 /* LaunchScreen.storyboard in Resources */,
3569CAA91EC1918E000C41C0 /* NohanaImagePicker.xcassets in Resources */,
F208E55B1CD7370B00FFC9F6 /* Assets.xcassets in Resources */,
F208E5591CD7370B00FFC9F6 /* Main.storyboard in Resources */,
);
@ -367,7 +355,7 @@
files = (
F23554261C69D19C00796DCA /* NohanaImagePicker.storyboard in Resources */,
F27029CB1C71C43A001647AB /* NohanaImagePicker.strings in Resources */,
F237249B1C6DCF96005D1E8A /* NohanaImagePicker.xcassets in Resources */,
F237249B1C6DCF96005D1E8A /* Images.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -389,12 +377,13 @@
files = (
F2DF3B171C6C868E00C1C0E4 /* AssetCell.swift in Sources */,
F26775E81C7073CD002E786C /* Size.swift in Sources */,
F26775DE1C701FA7002E786C /* ItemList.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 */,
@ -409,6 +398,7 @@
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 */,
);
@ -446,8 +436,6 @@
children = (
F27029CC1C71C43A001647AB /* en */,
F27029CF1C71C4FE001647AB /* ja */,
3590F1F51EC1A79400F32E06 /* ru */,
23D1CD93207CEB1200F8115E /* de */,
);
name = NohanaImagePicker.strings;
sourceTree = "<group>";
@ -465,8 +453,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = jp.co.nohana.NohanaImagePicker.Demo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
@ -480,8 +466,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = jp.co.nohana.NohanaImagePicker.Demo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
};
name = Release;
};
@ -494,22 +478,14 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@ -533,12 +509,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 2.3;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -554,22 +530,14 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@ -587,11 +555,11 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 2.3;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
@ -616,8 +584,6 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.2;
};
name = Debug;
};
@ -637,8 +603,6 @@
PRODUCT_BUNDLE_IDENTIFIER = jp.co.nohana.NohanaImagePicker;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.2;
};
name = Release;
};

View File

@ -1,8 +0,0 @@
<?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>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1000"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -16,12 +16,12 @@
public protocol ActivityIndicatable {
func isProgressing() -> Bool
func updateVisibilityOfActivityIndicator(_ activityIndicator: UIView)
func updateVisibilityOfActivityIndicator(activityIndicator: UIView)
}
public extension ActivityIndicatable where Self: UIViewController {
func updateVisibilityOfActivityIndicator(_ activityIndicator: UIView) {
func updateVisibilityOfActivityIndicator(activityIndicator: UIView) {
if isProgressing() {
if !view.subviews.contains(activityIndicator) {
view.addSubview(activityIndicator)
@ -30,4 +30,4 @@ public extension ActivityIndicatable where Self: UIViewController {
activityIndicator.removeFromSuperview()
}
}
}
}

View File

@ -15,32 +15,32 @@
*/
class AlbumListEmptyIndicator: UILabel {
init(message: String, description: String, frame: CGRect, config: NohanaImagePickerController.Config) {
init(message: String, description: String, frame: CGRect) {
super.init(frame: frame)
let centerStyle = NSMutableParagraphStyle()
centerStyle.alignment = NSTextAlignment.center
centerStyle.alignment = NSTextAlignment.Center
let messageAttributes = [
NSAttributedString.Key.foregroundColor : config.color.empty ?? UIColor(red: 0x88/0xff, green: 0x88/0xff, blue: 0x88/0xff, alpha: 1),
NSAttributedString.Key.font : UIFont.systemFont(ofSize: 26),
NSAttributedString.Key.paragraphStyle : centerStyle
NSForegroundColorAttributeName : ColorConfig.emptyIndicator,
NSFontAttributeName : UIFont.systemFontOfSize(26),
NSParagraphStyleAttributeName : centerStyle
]
let messageText = NSAttributedString(string: message, attributes: messageAttributes)
let descriptionAttributes = [
NSAttributedString.Key.foregroundColor : config.color.empty ?? UIColor(red: 0x88/0xff, green: 0x88/0xff, blue: 0x88/0xff, alpha: 1),
NSAttributedString.Key.font : UIFont.systemFont(ofSize: 14),
NSAttributedString.Key.paragraphStyle : centerStyle
NSForegroundColorAttributeName : ColorConfig.emptyIndicator,
NSFontAttributeName : UIFont.systemFontOfSize(14),
NSParagraphStyleAttributeName : centerStyle
]
let descriptionText = NSAttributedString(string: description, attributes: descriptionAttributes)
let attributedText = NSMutableAttributedString()
attributedText.append(messageText)
attributedText.append(NSAttributedString(string: "\n\n", attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 6)]))
attributedText.append(descriptionText)
attributedText.appendAttributedString(messageText)
attributedText.appendAttributedString(NSAttributedString(string: "\n\n", attributes: [NSFontAttributeName : UIFont.systemFontOfSize(6)]))
attributedText.appendAttributedString(descriptionText)
self.numberOfLines = 0
self.attributedText = attributedText
}
@ -48,4 +48,4 @@ class AlbumListEmptyIndicator: UILabel {
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
}

View File

@ -18,11 +18,11 @@ import UIKit
import Photos
class AlbumListViewController: UITableViewController, EmptyIndicatable, ActivityIndicatable {
enum AlbumListViewControllerSectionType: Int {
case moment = 0
case albums
case Moment = 0
case Albums
static func count() -> Int {
var count: Int = 0
for i in 0..<Int.max {
@ -34,44 +34,44 @@ class AlbumListViewController: UITableViewController, EmptyIndicatable, Activity
return count
}
}
weak var nohanaImagePickerController: NohanaImagePickerController?
var photoKitAlbumList: PhotoKitAlbumList!
override func viewDidLoad() {
super.viewDidLoad()
if let nohanaImagePickerController = nohanaImagePickerController {
view.backgroundColor = nohanaImagePickerController.config.color.background ?? .white
title = nohanaImagePickerController.config.strings.albumListTitle ?? NSLocalizedString("albumlist.title", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController.assetBundle, comment: "")
title = NSLocalizedString("albumlist.title", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController.assetBundle, comment: "")
setUpToolbarItems()
navigationController?.setToolbarHidden(nohanaImagePickerController.toolbarHidden, animated: false)
navigationController?.setToolbarHidden(nohanaImagePickerController.toolbarHidden ?? false, animated: false)
}
setUpEmptyIndicator()
setUpActivityIndicator()
self.view.backgroundColor = ColorConfig.backgroundColor
}
deinit {
NotificationCenter.default.removeObserver(self)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
override func viewWillAppear(_ animated: Bool) {
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if let nohanaImagePickerController = nohanaImagePickerController {
setToolbarTitle(nohanaImagePickerController)
}
if let indexPathForSelectedRow = tableView.indexPathForSelectedRow {
tableView.deselectRow(at: indexPathForSelectedRow, animated: true)
tableView.deselectRowAtIndexPath(indexPathForSelectedRow, animated: true)
}
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
tableView.reloadData()
}
// MARK: - UITableViewDelegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
guard let sectionType = AlbumListViewControllerSectionType(rawValue: indexPath.section) else {
fatalError("Invalid section")
}
@ -79,86 +79,83 @@ class AlbumListViewController: UITableViewController, EmptyIndicatable, Activity
return
}
switch sectionType {
case .moment:
case .Moment:
nohanaImagePickerController.delegate?.nohanaImagePickerDidSelectMoment?(nohanaImagePickerController)
case .albums:
case .Albums:
nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, didSelectPhotoKitAssetList: photoKitAlbumList[indexPath.row].assetList)
}
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
guard let sectionType = AlbumListViewControllerSectionType(rawValue: indexPath.section) else {
fatalError("Invalid section")
}
switch sectionType {
case .moment:
case .Moment:
return 52
case .albums:
case .Albums:
return 82
}
}
// MARK: - UITableViewDataSource
override func numberOfSections(in tableView: UITableView) -> Int {
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return AlbumListViewControllerSectionType.count()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let emptyIndicator = emptyIndicator {
updateVisibilityOfEmptyIndicator(emptyIndicator)
}
if let activityIndicator = activityIndicator {
updateVisibilityOfActivityIndicator(activityIndicator)
}
guard let sectionType = AlbumListViewControllerSectionType(rawValue: section) else {
fatalError("Invalid section")
}
switch sectionType {
case .moment:
case .Moment:
if let nohanaImagePickerController = nohanaImagePickerController {
return nohanaImagePickerController.shouldShowMoment ? 1 : 0
}
return 0
case .albums:
case .Albums:
return photoKitAlbumList.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
guard let sectionType = AlbumListViewControllerSectionType(rawValue: indexPath.section) else {
fatalError("Invalid section")
}
switch sectionType {
case .moment:
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MomentAlbumCell") as? MomentCell else {
case .Moment:
guard let cell = tableView.dequeueReusableCellWithIdentifier("MomentAlbumCell") as? AlbumCell else {
fatalError("failed to dequeueReusableCellWithIdentifier(\"MomentAlbumCell\")")
}
if let nohanaImagePickerController = nohanaImagePickerController {
cell.config = nohanaImagePickerController.config
cell.titleLabel?.text = nohanaImagePickerController.config.strings.albumListMomentTitle ?? NSLocalizedString("albumlist.moment.title", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController.assetBundle, comment: "")
cell.titleLabel?.text = NSLocalizedString("albumlist.moment.title", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController.assetBundle, comment: "")
}
return cell
case .albums:
guard let cell = tableView.dequeueReusableCell(withIdentifier: "AlbumCell") as? AlbumCell else {
case .Albums:
guard let cell = tableView.dequeueReusableCellWithIdentifier("AlbumCell") as? AlbumCell else {
fatalError("failed to dequeueReusableCellWithIdentifier(\"AlbumCell\")")
}
let albumList = photoKitAlbumList[indexPath.row]
cell.titleLabel.text = albumList.title
cell.tag = indexPath.row
let imageSize = CGSize(
width: cell.thumbnailImageView.frame.size.width * UIScreen.main.scale,
height: cell.thumbnailImageView.frame.size.width * UIScreen.main.scale
width: cell.thumbnailImageView.frame.size.width * UIScreen.mainScreen().scale,
height: cell.thumbnailImageView.frame.size.width * UIScreen.mainScreen().scale
)
let albumCount = albumList.count
if albumCount > 0 {
let lastAsset = albumList[albumCount - 1]
lastAsset.image(targetSize: imageSize, handler: { (imageData) -> Void in
DispatchQueue.main.async(execute: { () -> Void in
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 == indexPath.row {
cell.thumbnailImageView.image = imageData.image
@ -172,134 +169,132 @@ class AlbumListViewController: UITableViewController, EmptyIndicatable, Activity
return cell
}
}
// MARK: - Storyboard
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let sectionType = AlbumListViewControllerSectionType(rawValue: tableView.indexPathForSelectedRow!.section) else {
fatalError("Invalid section")
}
switch sectionType {
case .moment:
let momentViewController = segue.destination as! MomentViewController
case .Moment:
let momentViewController = segue.destinationViewController as! MomentViewController
momentViewController.nohanaImagePickerController = nohanaImagePickerController
momentViewController.momentAlbumList = PhotoKitAlbumList(
assetCollectionTypes: [.moment],
assetCollectionSubtypes: [.any],
assetCollectionTypes: [.Moment],
assetCollectionSubtypes: [.Any],
mediaType: nohanaImagePickerController!.mediaType,
shouldShowEmptyAlbum: nohanaImagePickerController!.shouldShowEmptyAlbum,
handler: { () -> Void in
DispatchQueue.main.async(execute: { [weak momentViewController] in
dispatch_async(dispatch_get_main_queue(), { [weak momentViewController] in
momentViewController?.isLoading = false
momentViewController?.collectionView?.reloadData()
momentViewController?.isFirstAppearance = true
momentViewController?.scrollCollectionViewToInitialPosition()
})
})
case .albums:
let assetListViewController = segue.destination as! AssetListViewController
case .Albums:
let assetListViewController = segue.destinationViewController as! AssetListViewController
assetListViewController.photoKitAssetList = photoKitAlbumList[tableView.indexPathForSelectedRow!.row]
assetListViewController.nohanaImagePickerController = nohanaImagePickerController
}
}
// MARK: - IBAction
@IBAction func didPushCancel(_ sender: AnyObject) {
@IBAction func didPushCancel(sender: AnyObject) {
if let nohanaImagePickerController = nohanaImagePickerController {
nohanaImagePickerController.delegate?.nohanaImagePickerDidCancel(nohanaImagePickerController)
}
}
// MARK: - EmptyIndicatable
var emptyIndicator: UIView?
func setUpEmptyIndicator() {
let frame = CGRect(origin: CGPoint.zero, size: Size.screenRectWithoutAppBar(self).size)
guard let nohanaImagePickerController = nohanaImagePickerController else {
return
}
emptyIndicator = AlbumListEmptyIndicator(
message: nohanaImagePickerController.config.strings.albumListEmptyMessage ?? NSLocalizedString("albumlist.empty.message", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController.assetBundle, comment: ""),
description: nohanaImagePickerController.config.strings.albumListEmptyDescription ?? NSLocalizedString("albumlist.empty.description", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController.assetBundle, comment: ""),
frame: frame,
config: nohanaImagePickerController.config)
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(style: .gray)
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
}
}
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.isEnabled = false
infoButton.setTitleTextAttributes([NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14), NSAttributedString.Key.foregroundColor: UIColor.black], for: UIControl.State())
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) {
let count: Int? = toolbarItems?.count
guard count != nil && count! >= 2 else {
func setToolbarTitle(nohanaImagePickerController:NohanaImagePickerController) {
guard toolbarItems?.count >= 2 else {
return
}
guard let infoButton = toolbarItems?[1] else {
return
}
if nohanaImagePickerController.maximumNumberOfSelection == 0 {
let title = String(format: nohanaImagePickerController.config.strings.toolbarTitleNoLimit ?? NSLocalizedString("toolbar.title.nolimit", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController.assetBundle, comment: ""),
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: nohanaImagePickerController.config.strings.toolbarTitleHasLimit ?? NSLocalizedString("toolbar.title.haslimit", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController.assetBundle, comment: ""),
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() {
NotificationCenter.default.addObserver(self, selector: #selector(AlbumListViewController.didPickPhotoKitAsset(_:)), name: NotificationInfo.Asset.PhotoKit.didPick, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(AlbumListViewController.didDropPhotoKitAsset(_:)), name: NotificationInfo.Asset.PhotoKit.didDrop, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(AlbumListViewController.didPickPhotoKitAsset(_:)), name: NotificationInfo.Asset.PhotoKit.didPick, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(AlbumListViewController.didDropPhotoKitAsset(_:)), name: NotificationInfo.Asset.PhotoKit.didDrop, object: nil)
}
@objc func didPickPhotoKitAsset(_ notification: Notification) {
func didPickPhotoKitAsset(notification: NSNotification) {
guard let picker = notification.object as? NohanaImagePickerController else {
return
}
setToolbarTitle(picker)
}
@objc func didDropPhotoKitAsset(_ notification: Notification) {
func didDropPhotoKitAsset(notification: NSNotification) {
guard let picker = notification.object as? NohanaImagePickerController else {
return
}

View File

@ -17,28 +17,28 @@
import UIKit
class AnimatableNavigationController: UINavigationController, UINavigationControllerDelegate {
let swipeInteractionController = SwipeInteractionController()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.delegate = self
}
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
switch operation {
case .push where fromVC is AssetListViewController:
case .Push where fromVC is AssetListViewController:
guard let fromVC = fromVC as? AssetListViewController,
let selectedIndex = fromVC.collectionView?.indexPathsForSelectedItems?.first,
let fromCell = fromVC.collectionView?.cellForItem(at: selectedIndex) as? AssetCell
selectedIndex = fromVC.collectionView?.indexPathsForSelectedItems()?.first,
fromCell = fromVC.collectionView?.cellForItemAtIndexPath(selectedIndex) as? AssetCell
else {
return nil
}
return ExpandingAnimationController(fromCell)
case .pop where toVC is AssetListViewController:
case .Pop where toVC is AssetListViewController:
guard let fromVC = fromVC as? AssetDetailListViewController,
let fromCell = fromVC.collectionView?.cellForItem(at: IndexPath(item: fromVC.currentIndexPath.item, section: 0)) as? AssetDetailCell
fromCell = fromVC.collectionView?.cellForItemAtIndexPath(NSIndexPath(forItem: fromVC.currentIndexPath.item, inSection: 0)) as? AssetDetailCell
else {
return nil
}
@ -47,12 +47,12 @@ class AnimatableNavigationController: UINavigationController, UINavigationContro
return nil
}
}
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
swipeInteractionController.attachToViewController(viewController)
}
func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
if animationController is ExpandingAnimationController {
return nil
}
@ -61,5 +61,5 @@ class AnimatableNavigationController: UINavigationController, UINavigationContro
}
return swipeInteractionController
}
}

View File

@ -16,46 +16,47 @@
import UIKit
class AssetCell: UICollectionViewCell {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var pickButton: UIButton!
@IBOutlet weak var overlayView: UIView!
weak var nohanaImagePickerController: NohanaImagePickerController?
var asset: Asset?
override func willMove(toSuperview newSuperview: UIView?) {
super.willMove(toSuperview: newSuperview)
var asset: AssetType?
override func willMoveToSuperview(newSuperview: UIView?) {
super.willMoveToSuperview(newSuperview)
if let nohanaImagePickerController = nohanaImagePickerController {
let droppedImage: UIImage? = nohanaImagePickerController.config.image.droppedSmall ?? UIImage(named: "btn_select_m", in: nohanaImagePickerController.assetBundle, compatibleWith: nil)
let pickedImage: UIImage? = nohanaImagePickerController.config.image.pickedSmall ?? UIImage(named: "btn_selected_m", in: nohanaImagePickerController.assetBundle, compatibleWith: nil)
pickButton.setImage(droppedImage, for: UIControl.State())
pickButton.setImage(pickedImage, for: .selected)
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) {
@IBAction func didPushPickButton(sender: UIButton) {
guard let asset = asset else {
return
}
if pickButton.isSelected {
if nohanaImagePickerController!.pickedAssetList.drop(asset: asset) {
pickButton.isSelected = false
if pickButton.selected {
if nohanaImagePickerController!.pickedAssetList.dropAsset(asset) {
pickButton.selected = false
}
} else {
if nohanaImagePickerController!.pickedAssetList.pick(asset: asset) {
pickButton.isSelected = true
if nohanaImagePickerController!.pickedAssetList.pickAsset(asset) {
pickButton.selected = true
}
}
self.overlayView.isHidden = !pickButton.isSelected
self.overlayView.hidden = !pickButton.selected
}
func update(asset: Asset, nohanaImagePickerController: NohanaImagePickerController) {
func update(asset: AssetType, nohanaImagePickerController: NohanaImagePickerController) {
self.asset = asset
self.nohanaImagePickerController = nohanaImagePickerController
self.pickButton.isSelected = nohanaImagePickerController.pickedAssetList.isPicked(asset)
self.overlayView.isHidden = !pickButton.isSelected
self.pickButton.isHidden = !(nohanaImagePickerController.canPickAsset(asset) )
self.pickButton.selected = nohanaImagePickerController.pickedAssetList.isPicked(asset) ?? false
self.overlayView.hidden = !pickButton.selected
self.pickButton.hidden = !(nohanaImagePickerController.canPickAsset(asset) ?? true)
}
}
}

View File

@ -17,58 +17,58 @@
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()
let doubleTapGestureRecognizer :UITapGestureRecognizer = UITapGestureRecognizer()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
doubleTapGestureRecognizer.addTarget(self, action: #selector(AssetDetailCell.didDoubleTap(_:)))
doubleTapGestureRecognizer.numberOfTapsRequired = 2
}
override func willMove(toSuperview newSuperview: UIView?) {
super.willMove(toSuperview: newSuperview)
override func willMoveToSuperview(newSuperview: UIView?) {
super.willMoveToSuperview(newSuperview)
scrollView.removeGestureRecognizer(doubleTapGestureRecognizer)
scrollView.addGestureRecognizer(doubleTapGestureRecognizer)
}
deinit {
scrollView.removeGestureRecognizer(doubleTapGestureRecognizer)
doubleTapGestureRecognizer.removeTarget(self, action: #selector(AssetDetailCell.didDoubleTap(_:)))
}
// MARK: - UIScrollViewDelegate
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imageView
}
// MARK: - Zoom
@objc func didDoubleTap(_ sender: UITapGestureRecognizer) {
func didDoubleTap(sender: UITapGestureRecognizer) {
if scrollView.zoomScale < scrollView.maximumZoomScale {
let center = sender.location(in: imageView)
scrollView.zoom(to: zoomRect(center), animated: true)
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 {
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
}
}
}

127
NohanaImagePicker/AssetDetailListViewController.swift Executable file → Normal file
View File

@ -17,113 +17,112 @@
import UIKit
class AssetDetailListViewController: AssetListViewController {
var currentIndexPath: IndexPath = IndexPath() {
var currentIndexPath: NSIndexPath = NSIndexPath() {
willSet {
if currentIndexPath != newValue {
didChangeAssetDetailPage(newValue)
}
}
}
@IBOutlet weak var imageCollectionView: UICollectionView!
@IBOutlet weak var pickButton: UIButton!
override var cellSize: CGSize {
return Size.screenRectWithoutAppBar(self).size
get {
return Size.screenRectWithoutAppBar(self).size
}
}
override func viewDidLoad() {
super.viewDidLoad()
if let nohanaImagePickerController = nohanaImagePickerController {
let droppedImage: UIImage? = nohanaImagePickerController.config.image.droppedLarge ?? UIImage(named: "btn_select_l", in: nohanaImagePickerController.assetBundle, compatibleWith: nil)
let pickedImage: UIImage? = nohanaImagePickerController.config.image.pickedLarge ?? UIImage(named: "btn_selected_l", in: nohanaImagePickerController.assetBundle, compatibleWith: nil)
let backgroundColor: UIColor = nohanaImagePickerController.config.color.background ?? .white
imageCollectionView.backgroundColor = backgroundColor
pickButton.setImage(droppedImage, for: UIControl.State())
pickButton.setImage(pickedImage, for: .selected)
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 viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
let indexPath = currentIndexPath
view.isHidden = true
coordinator.animate(alongsideTransition: nil) { _ in
view.hidden = true
coordinator.animateAlongsideTransition(nil) { _ in
self.view.invalidateIntrinsicContentSize()
self.collectionView?.reloadData()
self.scrollCollectionView(to: indexPath)
self.view.isHidden = false
self.view.hidden = false
}
}
override func updateTitle() {
self.title = ""
}
func didChangeAssetDetailPage(_ indexPath: IndexPath) {
func didChangeAssetDetailPage(indexPath:NSIndexPath) {
guard let nohanaImagePickerController = nohanaImagePickerController else {
return
}
let asset = photoKitAssetList[indexPath.item]
pickButton.isSelected = nohanaImagePickerController.pickedAssetList.isPicked(asset)
pickButton.isHidden = !(nohanaImagePickerController.canPickAsset(asset) )
pickButton.selected = nohanaImagePickerController.pickedAssetList.isPicked(asset) ?? false
pickButton.hidden = !(nohanaImagePickerController.canPickAsset(asset) ?? true)
nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, assetDetailListViewController: self, didChangeAssetDetailPage: indexPath, photoKitAsset: asset.originalAsset)
}
override func scrollCollectionView(to indexPath: IndexPath) {
let count: Int? = photoKitAssetList?.count
guard count != nil && count! > 0 else {
override func scrollCollectionView(to indexPath: NSIndexPath) {
guard photoKitAssetList?.count > 0 else {
return
}
DispatchQueue.main.async {
let toIndexPath = IndexPath(item: indexPath.item, section: 0)
self.collectionView?.scrollToItem(at: toIndexPath, at: UICollectionView.ScrollPosition.centeredHorizontally, animated: false)
dispatch_async(dispatch_get_main_queue()) {
let toIndexPath = NSIndexPath(forItem: indexPath.item, inSection: 0)
self.collectionView?.scrollToItemAtIndexPath(toIndexPath, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: false)
}
}
override func scrollCollectionViewToInitialPosition() {
guard isFirstAppearance else {
return
}
let indexPath = IndexPath(row: currentIndexPath.item, section: 0)
let indexPath = NSIndexPath(forRow: currentIndexPath.item, inSection: 0)
scrollCollectionView(to: indexPath)
isFirstAppearance = false
}
// MARK: - IBAction
@IBAction func didPushPickButton(_ sender: UIButton) {
@IBAction func didPushPickButton(sender: UIButton) {
let asset = photoKitAssetList[currentIndexPath.row]
if pickButton.isSelected {
if nohanaImagePickerController!.pickedAssetList.drop(asset: asset) {
pickButton.isSelected = false
if pickButton.selected {
if nohanaImagePickerController!.pickedAssetList.dropAsset(asset) {
pickButton.selected = false
}
} else {
if nohanaImagePickerController!.pickedAssetList.pick(asset: asset) {
pickButton.isSelected = true
if nohanaImagePickerController!.pickedAssetList.pickAsset(asset) {
pickButton.selected = true
}
}
}
// MARK: - UICollectionViewDelegate
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AssetDetailCell", for: indexPath) as? AssetDetailCell,
let nohanaImagePickerController = nohanaImagePickerController else {
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCellWithReuseIdentifier("AssetDetailCell", forIndexPath: indexPath) as? AssetDetailCell,
nohanaImagePickerController = nohanaImagePickerController else {
fatalError("failed to dequeueReusableCellWithIdentifier(\"AssetDetailCell\")")
}
cell.scrollView.zoomScale = 1
cell.tag = indexPath.item
let imageSize = CGSize(
width: cellSize.width * UIScreen.main.scale,
height: cellSize.height * UIScreen.main.scale
width: cellSize.width * UIScreen.mainScreen().scale,
height: cellSize.height * UIScreen.mainScreen().scale
)
let asset = photoKitAssetList[indexPath.item]
asset.image(targetSize: imageSize) { (imageData) -> Void in
DispatchQueue.main.async(execute: { () -> Void in
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
@ -135,27 +134,27 @@ class AssetDetailListViewController: AssetListViewController {
}
return (nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, assetDetailListViewController: self, cell: cell, indexPath: indexPath, photoKitAsset: asset.originalAsset)) ?? cell
}
// MARK: - UIScrollViewDelegate
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
override func scrollViewDidScroll(scrollView: UIScrollView) {
guard let collectionView = collectionView else {
return
}
let row = Int((collectionView.contentOffset.x + cellSize.width * 0.5) / cellSize.width)
if row < 0 {
currentIndexPath = IndexPath(row: 0, section: currentIndexPath.section)
} else if row >= collectionView.numberOfItems(inSection: 0) {
currentIndexPath = IndexPath(row: collectionView.numberOfItems(inSection: 0) - 1, section: currentIndexPath.section)
currentIndexPath = NSIndexPath(forRow: 0, inSection: currentIndexPath.section)
} else if row >= collectionView.numberOfItemsInSection(0) {
currentIndexPath = NSIndexPath(forRow: collectionView.numberOfItemsInSection(0) - 1, inSection: currentIndexPath.section)
} else {
currentIndexPath = IndexPath(row: row, section: currentIndexPath.section)
currentIndexPath = NSIndexPath(forRow: row, inSection: currentIndexPath.section)
}
}
// MARK: - UICollectionViewDelegateFlowLayout
override func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
override func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return cellSize
}
}
}

View File

@ -17,37 +17,39 @@
import UIKit
import Photos
class AssetListViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
class AssetListViewController: UICollectionViewController {
weak var nohanaImagePickerController: NohanaImagePickerController?
var photoKitAssetList: PhotoKitAssetList!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = nohanaImagePickerController?.config.color.background ?? .white
updateTitle()
setUpToolbarItems()
addPickPhotoKitAssetNotificationObservers()
self.view.backgroundColor = ColorConfig.backgroundColor
}
var cellSize: CGSize {
guard let nohanaImagePickerController = nohanaImagePickerController else {
return CGSize.zero
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)
}
var numberOfColumns = nohanaImagePickerController.numberOfColumnsInLandscape
if UIApplication.shared.statusBarOrientation.isPortrait {
numberOfColumns = nohanaImagePickerController.numberOfColumnsInPortrait
}
let cellMargin: CGFloat = 1
let cellWidth = (view.frame.width - cellMargin * (CGFloat(numberOfColumns) - 1)) / CGFloat(numberOfColumns)
return CGSize(width: cellWidth, height: cellWidth)
}
deinit {
NotificationCenter.default.removeObserver(self)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
override func viewWillAppear(_ animated: Bool) {
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if let nohanaImagePickerController = nohanaImagePickerController {
setToolbarTitle(nohanaImagePickerController)
@ -55,75 +57,74 @@ class AssetListViewController: UICollectionViewController, UICollectionViewDeleg
collectionView?.reloadData()
scrollCollectionViewToInitialPosition()
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
view.isHidden = true
coordinator.animate(alongsideTransition: nil) { _ in
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
view.hidden = true
coordinator.animateAlongsideTransition(nil) { _ in
// http://saygoodnight.com/2015/06/18/openpics-swift-rotation.html
if self.navigationController?.visibleViewController != self {
self.view.frame = CGRect(x: self.view.frame.origin.x, y: self.view.frame.origin.y, width: size.width, height: size.height)
self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, size.width, size.height)
}
self.collectionView?.reloadData()
self.scrollCollectionViewToInitialPosition()
self.view.isHidden = false
self.view.hidden = false
}
}
var isFirstAppearance = true
func updateTitle() {
title = photoKitAssetList.title
}
func scrollCollectionView(to indexPath: IndexPath) {
let count: Int? = photoKitAssetList?.count
guard count != nil && count! > 0 else {
func scrollCollectionView(to indexPath: NSIndexPath) {
guard photoKitAssetList?.count > 0 else {
return
}
DispatchQueue.main.async {
self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: false)
dispatch_async(dispatch_get_main_queue()) {
self.collectionView?.scrollToItemAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: false)
}
}
func scrollCollectionViewToInitialPosition() {
guard isFirstAppearance else {
return
}
let indexPath = IndexPath(item: self.photoKitAssetList.count - 1, section: 0)
let indexPath = NSIndexPath(forItem: self.photoKitAssetList.count - 1, inSection: 0)
self.scrollCollectionView(to: indexPath)
isFirstAppearance = false
}
// MARK: - UICollectionViewDataSource
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// MARK: - UICollectionViewDataSource
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return photoKitAssetList.count
}
// MARK: - UICollectionViewDelegate
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
if let nohanaImagePickerController = nohanaImagePickerController {
nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, didSelectPhotoKitAsset: photoKitAssetList[indexPath.item].originalAsset)
}
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AssetCell", for: indexPath) as? AssetCell,
let nohanaImagePickerController = nohanaImagePickerController else {
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCellWithReuseIdentifier("AssetCell", forIndexPath: indexPath) as? AssetCell,
nohanaImagePickerController = nohanaImagePickerController else {
fatalError("failed to dequeueReusableCellWithIdentifier(\"AssetCell\")")
}
cell.tag = indexPath.item
cell.update(asset: photoKitAssetList[indexPath.row], nohanaImagePickerController: nohanaImagePickerController)
cell.update(photoKitAssetList[indexPath.row], nohanaImagePickerController: nohanaImagePickerController)
let imageSize = CGSize(
width: cellSize.width * UIScreen.main.scale,
height: cellSize.height * UIScreen.main.scale
width: cellSize.width * UIScreen.mainScreen().scale,
height: cellSize.height * UIScreen.mainScreen().scale
)
let asset = photoKitAssetList[indexPath.item]
asset.image(targetSize: imageSize) { (imageData) -> Void in
DispatchQueue.main.async(execute: { () -> Void in
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
@ -133,29 +134,31 @@ class AssetListViewController: UICollectionViewController, UICollectionViewDeleg
}
return (nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, assetListViewController: self, cell: cell, indexPath: indexPath, photoKitAsset: asset.originalAsset)) ?? cell
}
// MARK: - UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return cellSize
}
// MARK: - Storyboard
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let selectedIndexPath = collectionView?.indexPathsForSelectedItems?.first else {
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let selectedIndexPath = collectionView?.indexPathsForSelectedItems()?.first else {
return
}
let assetListDetailViewController = segue.destination as! AssetDetailListViewController
let assetListDetailViewController = segue.destinationViewController as! AssetDetailListViewController
assetListDetailViewController.photoKitAssetList = photoKitAssetList
assetListDetailViewController.nohanaImagePickerController = nohanaImagePickerController
assetListDetailViewController.currentIndexPath = selectedIndexPath
}
// MARK: - IBAction
@IBAction func didPushDone(_ sender: AnyObject) {
let pickedPhotoKitAssets = nohanaImagePickerController!.pickedAssetList.map { ($0 as! PhotoKitAsset).originalAsset }
@IBAction func didPushDone(sender: AnyObject) {
let pickedPhotoKitAssets = nohanaImagePickerController!.pickedAssetList.map{ ($0 as! PhotoKitAsset).originalAsset }
nohanaImagePickerController!.delegate?.nohanaImagePicker(nohanaImagePickerController!, didFinishPickingPhotoKitAssets: pickedPhotoKitAssets )
}
}

View File

@ -14,9 +14,11 @@
* limitations under the License.
*/
"albumlist.title" = "Fotos";
"albumlist.empty.message" = "Keine Fotos";
"albumlist.empty.description" = "Nimm Fotos mit der Kamera App auf.";
"albumlist.moment.title" = "Moment";
"toolbar.title.nolimit" = "Ausgewählte Fotos: %ld";
"toolbar.title.haslimit" = "Ausgewählte Fotos: %ld / %ld";
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)
}
}

View File

@ -17,13 +17,13 @@
import AVFoundation
extension Size {
static func contractingAnimationToCellRect(_ toVC: AssetListViewController, toCell: AssetCell) -> CGRect {
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 = AVMakeRect(aspectRatio: contractingImageSize, insideRect: fromCell.imageView.frame)
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
@ -32,63 +32,64 @@ extension Size {
}
class ContractingAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
var fromCell: AssetDetailCell
init(_ fromCell: AssetDetailCell) {
self.fromCell = fromCell
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.3
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
guard
let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from) as? AssetDetailListViewController,
let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) as? AssetListViewController
let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as? AssetDetailListViewController,
toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as? AssetListViewController
else {
return
}
var toCellTmp = toVC.collectionView?.cellForItem(at: fromVC.currentIndexPath as IndexPath) as? AssetCell
var toCellTmp = toVC.collectionView?.cellForItemAtIndexPath(fromVC.currentIndexPath) as? AssetCell
if toCellTmp == nil {
// if toCell is not shown in collection view, scroll collection view to toCell index path.
toVC.collectionView?.scrollToItem(at: fromVC.currentIndexPath as IndexPath, at: .centeredVertically, animated: false)
toVC.collectionView?.scrollToItemAtIndexPath(fromVC.currentIndexPath, atScrollPosition: .CenteredVertically, animated: false)
toVC.collectionView?.layoutIfNeeded()
toCellTmp = toVC.collectionView?.cellForItem(at: fromVC.currentIndexPath as IndexPath) as? AssetCell
toCellTmp = toVC.collectionView?.cellForItemAtIndexPath(fromVC.currentIndexPath) 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)
transitionContext.containerView.addSubview(toVC.view)
transitionContext.containerView.addSubview(contractingImageView)
let containerView = transitionContext.containerView()
containerView.addSubview(toVC.view)
containerView.addSubview(contractingImageView)
toVC.view.alpha = 0
fromCell.alpha = 0
toCell.alpha = 0
UIView.animate(
withDuration: transitionDuration(using: transitionContext),
UIView.animateWithDuration(
transitionDuration(transitionContext),
delay: 0,
options: UIView.AnimationOptions(),
animations: {
options: .CurveEaseInOut,
animations: { _ in
toVC.view.alpha = 1
contractingImageView.frame = Size.contractingAnimationToCellRect(toVC, toCell: toCell)
}) { _ in
self.fromCell.alpha = 1
toCell.alpha = 1
contractingImageView.removeFromSuperview()
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
}
}
}

View File

@ -16,12 +16,12 @@
public protocol EmptyIndicatable {
func isEmpty() -> Bool
func updateVisibilityOfEmptyIndicator(_ emptyIndicator: UIView)
func updateVisibilityOfEmptyIndicator(emptyIndicator: UIView)
}
public extension EmptyIndicatable where Self: UIViewController {
func updateVisibilityOfEmptyIndicator(_ emptyIndicator: UIView) {
if isEmpty() {
func updateVisibilityOfEmptyIndicator(emptyIndicator: UIView) {
if isEmpty(){
if !view.subviews.contains(emptyIndicator) {
view.addSubview(emptyIndicator)
}
@ -29,4 +29,4 @@ public extension EmptyIndicatable where Self: UIViewController {
emptyIndicator.removeFromSuperview()
}
}
}
}

50
NohanaImagePicker/ExpandingAnimationController.swift Executable file → Normal file
View File

@ -18,62 +18,64 @@ import AVFoundation
extension Size {
static func expandingAnimationFromCellRect(_ fromVC: AssetListViewController, fromCell: AssetCell) -> CGRect {
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 AVMakeRect(aspectRatio: toSize, insideRect: Size.screenRectWithoutAppBar(fromVC))
static func expandingAnimationToCellRect(fromVC: UIViewController, toSize:CGSize) -> CGRect {
return AVMakeRectWithAspectRatioInsideRect(toSize, Size.screenRectWithoutAppBar(fromVC))
}
}
class ExpandingAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
var fromCell: AssetCell
init(_ fromCell: AssetCell) {
self.fromCell = fromCell
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.3
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from) as? AssetListViewController,
let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) as? AssetDetailListViewController
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
guard let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as? AssetListViewController,
toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as? AssetDetailListViewController
else {
return
}
let expandingImageView = UIImageView(image: fromCell.imageView.image)
expandingImageView.contentMode = fromCell.imageView.contentMode
expandingImageView.clipsToBounds = true
expandingImageView.frame = Size.expandingAnimationFromCellRect(fromVC, fromCell: fromCell)
transitionContext.containerView.addSubview(toVC.view)
transitionContext.containerView.addSubview(expandingImageView)
let containerView = transitionContext.containerView()
containerView.addSubview(toVC.view)
containerView.addSubview(expandingImageView)
toVC.view.alpha = 0
toVC.collectionView?.isHidden = true
toVC.view.backgroundColor = .white
toVC.collectionView?.hidden = true
toVC.view.backgroundColor = UIColor.blackColor()
fromCell.alpha = 0
UIView.animate(
withDuration: transitionDuration(using: transitionContext),
UIView.animateWithDuration(
transitionDuration(transitionContext),
delay: 0,
usingSpringWithDamping: 0.8,
initialSpringVelocity: 10,
options: .curveEaseOut,
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?.isHidden = false
toVC.collectionView?.hidden = false
expandingImageView.removeFromSuperview()
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
}
}
}

View File

@ -14,9 +14,17 @@
* limitations under the License.
*/
"albumlist.title" = "Фотографии";
"albumlist.empty.message" = "Нет фотографий";
"albumlist.empty.description" = "Получить фото с камеры";
"albumlist.moment.title" = "Моменты";
"toolbar.title.nolimit" = "Выбрано: %ld";
"toolbar.title.haslimit" = "Выбрано: %ld / %ld";
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"
}
}
}
}

View File

@ -6,12 +6,12 @@
},
{
"idiom" : "universal",
"filename" : "btn_selected_m@2x.png",
"filename" : "icon_photosize_alert_s@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "btn_selected_m@3x.png",
"filename" : "icon_photosize_alert_s@3x.png",
"scale" : "3x"
}
],

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -6,12 +6,12 @@
},
{
"idiom" : "universal",
"filename" : "btn_select_m@2x.png",
"filename" : "icon_photosize_low_s@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "btn_select_m@3x.png",
"filename" : "icon_photosize_low_s@3x.png",
"scale" : "3x"
}
],

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -14,25 +14,19 @@
* limitations under the License.
*/
public protocol ItemList: Collection {
public protocol ItemListType: CollectionType {
associatedtype Item
var title: String { get }
func update(_ handler:(() -> Void)?)
var title:String { get }
func update(handler:(() -> Void)?)
subscript (index: Int) -> Item { get }
}
extension ItemList {
public func index(after i: Int) -> Int {
return i + 1
}
}
public protocol Asset {
var identifier: Int { get }
func image(targetSize: CGSize, handler: @escaping (ImageData?) -> Void)
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>?
}
}

View File

@ -17,13 +17,11 @@
import UIKit
class MomentCell: AlbumCell {
var config: NohanaImagePickerController.Config!
override func draw(_ rect: CGRect) {
super.draw(rect)
let lineWidth: CGFloat = 1 / UIScreen.main.scale
let separatorColor: UIColor = config.color.separator ?? UIColor(red: 0xbb/0xff, green: 0xbb/0xff, blue: 0xbb/0xff, alpha: 1)
separatorColor.setFill()
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))
}

View File

@ -18,30 +18,29 @@ import UIKit
import Photos
class MomentViewController: AssetListViewController, ActivityIndicatable {
var momentAlbumList: PhotoKitAlbumList!
override func viewDidLoad() {
super.viewDidLoad()
setUpActivityIndicator()
}
override func updateTitle() {
if let nohanaImagePickerController = nohanaImagePickerController {
title = NSLocalizedString("albumlist.moment.title", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController.assetBundle, comment: "")
}
}
override func scrollCollectionView(to indexPath: IndexPath) {
let count: Int? = momentAlbumList?.count
guard count != nil && count! > 0 else {
override func scrollCollectionView(to indexPath: NSIndexPath) {
guard momentAlbumList?.count > 0 else {
return
}
DispatchQueue.main.async {
self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: false)
dispatch_async(dispatch_get_main_queue()) {
self.collectionView?.scrollToItemAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: false)
}
}
override func scrollCollectionViewToInitialPosition() {
guard isFirstAppearance else {
return
@ -50,43 +49,43 @@ class MomentViewController: AssetListViewController, ActivityIndicatable {
guard lastSection >= 0 else {
return
}
let indexPath = IndexPath(item: momentAlbumList[lastSection].count - 1, section: lastSection)
let indexPath = NSIndexPath(forItem: momentAlbumList[lastSection].count - 1, inSection: lastSection)
scrollCollectionView(to: indexPath)
isFirstAppearance = false
}
// MARK: - UICollectionViewDataSource
override func numberOfSections(in collectionView: UICollectionView) -> Int {
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
if let activityIndicator = activityIndicator {
updateVisibilityOfActivityIndicator(activityIndicator)
}
return momentAlbumList.count
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return momentAlbumList[section].count
}
// MARK: - UICollectionViewDelegate
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AssetCell", for: indexPath) as? AssetCell,
let nohanaImagePickerController = nohanaImagePickerController else {
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCellWithReuseIdentifier("AssetCell", forIndexPath: indexPath) as? AssetCell,
nohanaImagePickerController = nohanaImagePickerController else {
fatalError("failed to dequeueReusableCellWithIdentifier(\"AssetCell\")")
}
let asset = momentAlbumList[indexPath.section][indexPath.row]
cell.tag = indexPath.item
cell.update(asset: asset, nohanaImagePickerController: nohanaImagePickerController)
cell.update(asset, nohanaImagePickerController: nohanaImagePickerController)
let imageSize = CGSize(
width: cellSize.width * UIScreen.main.scale,
height: cellSize.height * UIScreen.main.scale
width: cellSize.width * UIScreen.mainScreen().scale,
height: cellSize.height * UIScreen.mainScreen().scale
)
asset.image(targetSize: imageSize) { (imageData) -> Void in
DispatchQueue.main.async(execute: { () -> Void in
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
@ -96,21 +95,21 @@ class MomentViewController: AssetListViewController, ActivityIndicatable {
}
return (nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, assetListViewController: self, cell: cell, indexPath: indexPath, photoKitAsset: asset.originalAsset)) ?? cell
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionView.elementKindSectionHeader:
case UICollectionElementKindSectionHeader:
let album = momentAlbumList[indexPath.section]
guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "MomentHeader", for: indexPath) as? MomentSectionHeaderView else {
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 = DateFormatter()
formatter.dateStyle = .long
formatter.timeStyle = DateFormatter.Style.none
header.dateLabel.text = formatter.string(from: date as Date)
} else {
let formatter = NSDateFormatter()
formatter.dateStyle = .LongStyle
formatter.timeStyle = NSDateFormatterStyle.NoStyle
header.dateLabel.text = formatter.stringFromDate(date)
} else {
header.dateLabel.text = ""
}
return header
@ -118,47 +117,47 @@ class MomentViewController: AssetListViewController, ActivityIndicatable {
fatalError("failed to create MomentHeader")
}
}
// MARK: - ActivityIndicatable
var activityIndicator: UIActivityIndicatorView?
var isLoading = true
func setUpActivityIndicator() {
activityIndicator = UIActivityIndicatorView(style: .gray)
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: - UICollectionViewDelegate
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
if let nohanaImagePickerController = nohanaImagePickerController {
nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, didSelectPhotoKitAsset: momentAlbumList[indexPath.section][indexPath.row].originalAsset)
}
}
// MARK: - Storyboard
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let selectedIndexPath = collectionView?.indexPathsForSelectedItems?.first else {
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let selectedIndexPath = collectionView?.indexPathsForSelectedItems()?.first else {
return
}
let assetListDetailViewController = segue.destination as! AssetDetailListViewController
let assetListDetailViewController = segue.destinationViewController as! AssetDetailListViewController
assetListDetailViewController.photoKitAssetList = momentAlbumList[selectedIndexPath.section]
assetListDetailViewController.nohanaImagePickerController = nohanaImagePickerController
assetListDetailViewController.currentIndexPath = selectedIndexPath
}
// MARK: - IBAction
@IBAction override func didPushDone(_ sender: AnyObject) {
@IBAction override func didPushDone(sender: AnyObject) {
super.didPushDone(sender)
}
}
}

View File

@ -1,41 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_0" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15G1004" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
</dependencies>
<scenes>
<!--Album List View Controller-->
<scene sceneID="q2I-uS-c5w">
<objects>
<tableViewController storyboardIdentifier="AlbumListViewController" id="KD8-91-yw0" customClass="AlbumListViewController" customModule="NohanaImagePicker" customModuleProvider="target" sceneMemberID="viewController">
<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" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<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="28" width="320" height="82"/>
<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="286" height="82"/>
<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="20" y="6" width="70" height="70"/>
<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="108" y="31.5" width="178" height="19.5"/>
<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="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@ -47,7 +47,7 @@
<constraint firstAttribute="trailingMargin" secondItem="YSz-MM-h6f" secondAttribute="trailing" constant="-8" id="tee-FS-sAo"/>
</constraints>
</tableViewCellContentView>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<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"/>
@ -55,19 +55,19 @@
</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="110" width="320" height="52"/>
<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="286" height="52"/>
<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="24" y="18" width="262" height="16"/>
<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="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@ -77,7 +77,7 @@
<constraint firstItem="nzC-P1-sBf" firstAttribute="centerY" secondItem="ZzC-oj-tew" secondAttribute="centerY" id="SZH-em-zj3"/>
</constraints>
</tableViewCellContentView>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<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"/>
@ -106,35 +106,34 @@
<!--Asset List View Controller-->
<scene sceneID="29G-N1-dd5">
<objects>
<collectionViewController storyboardIdentifier="AssetListViewController" id="5jk-x3-LYk" customClass="AssetListViewController" customModule="NohanaImagePicker" customModuleProvider="target" sceneMemberID="viewController">
<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" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="1" minimumInteritemSpacing="1" id="xXL-vg-bZb">
<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="0.0" maxX="0.0" maxY="0.0"/>
<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="0.0" width="78" height="78"/>
<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="20" width="78" height="58"/>
<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="20" width="78" height="58"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<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="right" contentVerticalAlignment="bottom" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="oDB-be-mWY">
<rect key="frame" x="26" y="26" width="44" height="44"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<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"/>
@ -145,17 +144,18 @@
</connections>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<constraints>
<constraint firstAttribute="trailing" secondItem="oDB-be-mWY" secondAttribute="trailing" constant="8" id="0u6-oO-0PG"/>
<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 firstAttribute="bottom" secondItem="oDB-be-mWY" secondAttribute="bottom" constant="8" id="hKA-oO-Fmk"/>
<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"/>
@ -168,7 +168,7 @@
</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="78" width="320" height="44"/>
<rect key="frame" x="0.0" y="152" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</collectionReusableView>
<connections>
@ -188,12 +188,12 @@
</collectionViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="1SX-Sl-Deo" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1749" y="214"/>
<point key="canvasLocation" x="1156" y="267"/>
</scene>
<!--Asset Detail List View Controller-->
<scene sceneID="jjo-0p-7dH">
<objects>
<collectionViewController storyboardIdentifier="AssetDetailListViewController" id="r7t-t8-AuE" customClass="AssetDetailListViewController" customModule="NohanaImagePicker" customModuleProvider="target" sceneMemberID="viewController">
<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"/>
@ -205,14 +205,14 @@
</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="92" width="320" height="320"/>
<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="20" width="320" height="300"/>
<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"/>
@ -234,6 +234,7 @@
</connections>
</scrollView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<gestureRecognizers/>
<constraints>
@ -258,8 +259,9 @@
<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="274" y="5" width="30" height="34"/>
<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>
@ -269,13 +271,12 @@
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<size key="freeformSize" width="320" height="568"/>
<connections>
<outlet property="imageCollectionView" destination="wIU-KV-n3W" id="9kr-es-gvr"/>
<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="2741" y="449"/>
<point key="canvasLocation" x="1598" y="456"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="RR9-zr-Qlw">
@ -285,7 +286,7 @@
<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="20" width="320" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
@ -295,7 +296,7 @@
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="3iI-ph-cZF" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-456" y="215"/>
<point key="canvasLocation" x="259" y="219"/>
</scene>
<!--Animatable Navigation Controller-->
<scene sceneID="Zpb-f1-dmj">
@ -304,7 +305,7 @@
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<size key="freeformSize" width="320" height="568"/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="BOZ-Zf-lAN">
<rect key="frame" x="0.0" y="20" width="320" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
@ -313,16 +314,16 @@
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Sfb-mw-QnO" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-458" y="935"/>
<point key="canvasLocation" x="259" y="882"/>
</scene>
<!--Moment View Controller-->
<scene sceneID="kJ6-NP-kmc">
<objects>
<collectionViewController storyboardIdentifier="MomentViewController" id="FOz-K3-QuR" customClass="MomentViewController" customModule="NohanaImagePicker" customModuleProvider="target" sceneMemberID="viewController">
<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" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<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"/>
@ -331,34 +332,37 @@
</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="46" width="78" height="78"/>
<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="20" width="78" height="58"/>
<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="20" width="78" height="58"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<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="26" width="44" height="44"/>
<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"/>
@ -366,7 +370,6 @@
<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"/>
<constraint firstAttribute="bottom" secondItem="vrt-tc-b54" secondAttribute="bottom" constant="8" id="z5g-3Q-yNU"/>
</constraints>
<size key="customSize" width="78" height="78"/>
<connections>
@ -378,17 +381,18 @@
</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="0.0" width="320" height="44"/>
<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="13.5" width="120" height="17"/>
<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="custom" customColorSpace="sRGB"/>
<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">
@ -397,9 +401,12 @@
</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="15" width="176" height="14.5"/>
<rect key="frame" x="132" y="12" width="176" height="21"/>
<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="custom" customColorSpace="sRGB"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@ -440,14 +447,15 @@
</collectionViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="A16-1a-z3b" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1751" y="965"/>
<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"/>
<segue reference="tQI-o9-h2w"/>
<segue reference="Bed-w3-B1Q"/>
</inferredMetricsTieBreakers>
</document>

View File

@ -1,6 +0,0 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -18,72 +18,70 @@ import UIKit
import Photos
public enum MediaType: Int {
case any = 0, photo, video
case Any = 0, Photo, Video
}
@objc public protocol NohanaImagePickerControllerDelegate {
func nohanaImagePickerDidCancel(_ picker: NohanaImagePickerController)
func nohanaImagePicker(_ picker: NohanaImagePickerController, didFinishPickingPhotoKitAssets pickedAssts: [PHAsset])
@objc optional func nohanaImagePicker(_ picker: NohanaImagePickerController, willPickPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int) -> Bool
@objc optional func nohanaImagePicker(_ picker: NohanaImagePickerController, didPickPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int)
@objc optional func nohanaImagePicker(_ picker: NohanaImagePickerController, willDropPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int) -> Bool
@objc optional func nohanaImagePicker(_ picker: NohanaImagePickerController, didDropPhotoKitAsset asset: PHAsset, pickedAssetsCount: Int)
@objc optional func nohanaImagePicker(_ picker: NohanaImagePickerController, didSelectPhotoKitAsset asset: PHAsset)
@objc optional func nohanaImagePicker(_ picker: NohanaImagePickerController, didSelectPhotoKitAssetList assetList: PHAssetCollection)
@objc optional func nohanaImagePickerDidSelectMoment(_ picker: NohanaImagePickerController) -> Void
@objc optional func nohanaImagePicker(_ picker: NohanaImagePickerController, assetListViewController: UICollectionViewController, cell: UICollectionViewCell, indexPath: IndexPath, photoKitAsset: PHAsset) -> UICollectionViewCell
@objc optional func nohanaImagePicker(_ picker: NohanaImagePickerController, assetDetailListViewController: UICollectionViewController, cell: UICollectionViewCell, indexPath: IndexPath, photoKitAsset: PHAsset) -> UICollectionViewCell
@objc optional func nohanaImagePicker(_ picker: NohanaImagePickerController, assetDetailListViewController: UICollectionViewController, didChangeAssetDetailPage indexPath: IndexPath, photoKitAsset: PHAsset)
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)
}
open class NohanaImagePickerController: UIViewController {
open var maximumNumberOfSelection: Int = 21 // set 0 to no limit
open var numberOfColumnsInPortrait: Int = 4
open var numberOfColumnsInLandscape: Int = 7
open weak var delegate: NohanaImagePickerControllerDelegate?
open var shouldShowMoment: Bool = true
open var shouldShowEmptyAlbum: Bool = false
open var toolbarHidden: Bool = false
open var canPickAsset = { (asset: Asset) -> Bool in
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
}
open var config: Config = Config()
lazy var assetBundle: Bundle = {
let bundle = Bundle(for: type(of: self))
if let path = bundle.path(forResource: "NohanaImagePicker", ofType: "bundle") {
return Bundle(path: path)!
lazy var assetBundle:NSBundle = {
let bundle = NSBundle(forClass: self.dynamicType)
if let path = bundle.pathForResource("NohanaImagePicker", ofType: "bundle") {
return NSBundle(path: path)!
}
return bundle
}()
let pickedAssetList: PickedAssetList
let mediaType: MediaType
let enableExpandingPhotoAnimation: Bool
fileprivate let assetCollectionSubtypes: [PHAssetCollectionSubtype]
private let assetCollectionSubtypes: [PHAssetCollectionSubtype]
public init() {
assetCollectionSubtypes = [
.albumRegular,
.albumSyncedEvent,
.albumSyncedFaces,
.albumSyncedAlbum,
.albumImported,
.albumMyPhotoStream,
.albumCloudShared,
.smartAlbumGeneric,
.smartAlbumFavorites,
.smartAlbumRecentlyAdded,
.smartAlbumUserLibrary
.AlbumRegular,
.AlbumSyncedEvent,
.AlbumSyncedFaces,
.AlbumSyncedAlbum,
.AlbumImported,
.AlbumMyPhotoStream,
.AlbumCloudShared,
.SmartAlbumGeneric,
.SmartAlbumFavorites,
.SmartAlbumRecentlyAdded,
.SmartAlbumUserLibrary
]
mediaType = .photo
mediaType = .Photo
pickedAssetList = PickedAssetList()
enableExpandingPhotoAnimation = true
super.init(nibName: nil, bundle: nil)
self.pickedAssetList.nohanaImagePickerController = self
}
public init(assetCollectionSubtypes: [PHAssetCollectionSubtype], mediaType: MediaType, enableExpandingPhotoAnimation: Bool) {
self.assetCollectionSubtypes = assetCollectionSubtypes
self.mediaType = mediaType
@ -97,72 +95,44 @@ open class NohanaImagePickerController: UIViewController {
fatalError("init(coder:) has not been implemented")
}
override open func viewDidLoad() {
override public func viewDidLoad() {
super.viewDidLoad()
// show albumListViewController
let storyboard = UIStoryboard(name: "NohanaImagePicker", bundle: assetBundle)
let viewControllerId = enableExpandingPhotoAnimation ? "EnableAnimationNavigationController" : "DisableAnimationNavigationController"
guard let navigationController = storyboard.instantiateViewController(withIdentifier: viewControllerId) as? UINavigationController else {
guard let navigationController = storyboard.instantiateViewControllerWithIdentifier(viewControllerId) as? UINavigationController else {
fatalError("navigationController init failed.")
}
addChild(navigationController)
addChildViewController(navigationController)
view.addSubview(navigationController.view)
navigationController.didMove(toParent: self)
navigationController.didMoveToParentViewController(self)
// setup albumListViewController
guard let albumListViewController = navigationController.topViewController as? AlbumListViewController else {
fatalError("albumListViewController is not topViewController.")
}
albumListViewController.photoKitAlbumList =
PhotoKitAlbumList(
assetCollectionTypes: [.smartAlbum, .album],
assetCollectionTypes: [.SmartAlbum, .Album],
assetCollectionSubtypes: assetCollectionSubtypes,
mediaType: mediaType,
shouldShowEmptyAlbum: shouldShowEmptyAlbum,
handler: { [weak albumListViewController] in
DispatchQueue.main.async(execute: { () -> Void in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
albumListViewController?.isLoading = false
albumListViewController?.tableView.reloadData()
})
})
albumListViewController.nohanaImagePickerController = self
}
open func pickAsset(_ asset: Asset) {
_ = pickedAssetList.pick(asset: asset)
public func pickAsset(asset: AssetType) {
pickedAssetList.pickAsset(asset)
}
open func dropAsset(_ asset: Asset) {
_ = pickedAssetList.drop(asset: asset)
public func dropAsset(asset: AssetType) {
pickedAssetList.dropAsset(asset)
}
}
extension NohanaImagePickerController {
public struct Config {
public struct Color {
public var background: UIColor?
public var empty: UIColor?
public var separator: UIColor?
}
public var color = Color()
public struct Image {
public var pickedSmall: UIImage?
public var pickedLarge: UIImage?
public var droppedSmall: UIImage?
public var droppedLarge: UIImage?
}
public var image = Image()
public struct Strings {
public var albumListTitle: String?
public var albumListMomentTitle: String?
public var albumListEmptyMessage: String?
public var albumListEmptyDescription: String?
public var toolbarTitleNoLimit: String?
public var toolbarTitleHasLimit: String?
}
public var strings = Strings()
}
}

View File

@ -17,12 +17,12 @@
struct NotificationInfo {
struct Asset {
struct PhotoKit {
static let didPick = Notification.Name("jp.co.nohana.NotificationName.Asset.PhotoKit.didPick")
static let didPick = "jp.co.nohana.NotificationName.Asset.PhotoKit.didPick"
static let didPickUserInfoKeyAsset = "asset"
static let didPickUserInfoKeyPickedAssetsCount = "pickedAssetsCount"
static let didDrop = Notification.Name("jp.co.nohana.NotificationName.Asset.PhotoKit.didDrop")
static let didDrop = "jp.co.nohana.NotificationName.Asset.PhotoKit.didDrop"
static let didDropUserInfoKeyAsset = "asset"
static let didDropUserInfoKeyPickedAssetsCount = "pickedAssetsCount"
}
}
}
}

View File

@ -15,14 +15,14 @@
*/
import Photos
public class PhotoKitAlbumList: ItemList {
private var albumList: [Item] = []
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)?) {
@ -36,58 +36,69 @@ public class PhotoKitAlbumList: ItemList {
}
}
}
// MARK: - ItemList
// MARK: - ItemListType
public typealias Item = PhotoKitAssetList
open var title: String {
return "PhotoKit"
public var title:String {
get {
return "PhotoKit"
}
}
open func update(_ handler:(() -> Void)?) {
DispatchQueue.global(qos: .default).async {
var albumListFetchResult: [PHFetchResult<PHAssetCollection>] = []
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.fetchAssetCollections(with: type, subtype: .any, options: nil)]
albumListFetchResult = albumListFetchResult + [PHAssetCollection.fetchAssetCollectionsWithType(type, subtype: .Any, options: nil)]
}
self.albumList = []
var tmpAlbumList: [Item] = []
let isAssetCollectionSubtypeAny = self.assetCollectionSubtypes.contains(.any)
var tmpAlbumList:[Item] = []
let isAssetCollectionSubtypeAny = self.assetCollectionSubtypes.contains(.Any)
for fetchResult in albumListFetchResult {
fetchResult.enumerateObjects({ (album, index, stop) in
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.fetchAssets(in: album, options: PhotoKitAssetList.fetchOptions(self.mediaType)).count != 0 {
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.sorted { $0.date!.timeIntervalSince1970 < $1.date!.timeIntervalSince1970 }
if self.assetCollectionTypes == [.Moment] {
self.albumList = tmpAlbumList.sort{ $0.date?.timeIntervalSince1970 < $1.date?.timeIntervalSince1970 }
} else {
self.albumList = tmpAlbumList
}
if let handler = handler {
handler()
}
}
}
open subscript (index: Int) -> Item {
return albumList[index] as Item
public subscript (index: Int) -> Item {
get {
return albumList[index] as Item
}
}
// MARK: - CollectionType
open var startIndex: Int {
return albumList.startIndex
public var startIndex: Int {
get {
return albumList.startIndex
}
}
open var endIndex: Int {
return albumList.endIndex
public var endIndex: Int {
get {
return albumList.endIndex
}
}
}

View File

@ -15,38 +15,42 @@
*/
import Photos
public class PhotoKitAsset: Asset {
public class PhotoKitAsset :AssetType {
let asset: PHAsset
public init(asset: PHAsset) {
self.asset = asset
}
public var originalAsset: PHAsset {
return asset as PHAsset
get {
return asset as PHAsset
}
}
// MARK: - Asset
public var identifier: Int {
return asset.localIdentifier.hash
// MARK: - AssetType
public var identifier:Int {
get {
return asset.localIdentifier.hash
}
}
public func image(targetSize: CGSize, handler: @escaping (ImageData?) -> Void) {
public func image(targetSize:CGSize, handler: (ImageData?) -> Void) {
let option = PHImageRequestOptions()
option.isNetworkAccessAllowed = true
_ = PHImageManager.default().requestImage(
for: self.asset,
option.networkAccessAllowed = true
PHImageManager.defaultManager().requestImageForAsset(
self.asset,
targetSize: targetSize,
contentMode: .aspectFit,
contentMode: .AspectFit,
options: option ) { (image, info) -> Void in
guard let image = image else {
handler(nil)
return
}
handler(ImageData(image: image, info: info as Dictionary<NSObject, AnyObject>?))
handler(ImageData(image: image, info: info))
}
}
}

View File

@ -16,59 +16,72 @@
import Photos
open class PhotoKitAssetList: ItemList {
fileprivate let mediaType: MediaType
public class PhotoKitAssetList :ItemListType {
private let mediaType: MediaType
public let assetList: PHAssetCollection
fileprivate var fetchResult: PHFetchResult<PHAsset>!
private var fetchResult: PHFetchResult!
init(album: PHAssetCollection, mediaType: MediaType) {
self.assetList = album
self.mediaType = mediaType
update()
}
// MARK: - ItemList
// MARK: - ItemListType
public typealias Item = PhotoKitAsset
open var title: String {
return assetList.localizedTitle ?? ""
public var title: String {
get{
return assetList.localizedTitle ?? ""
}
}
open var date: Date? {
return assetList.startDate
public var date: NSDate? {
get {
return assetList.startDate
}
}
class func fetchOptions(_ mediaType: MediaType) -> PHFetchOptions {
class func fetchOptions(mediaType: MediaType) -> PHFetchOptions {
let options = PHFetchOptions()
switch mediaType {
case .photo:
options.predicate = NSPredicate(format: "mediaType == %ld", PHAssetMediaType.image.rawValue)
case .Photo:
options.predicate = NSPredicate(format: "mediaType == %ld", PHAssetMediaType.Image.rawValue)
default:
fatalError("not supported .Video and .Any yet")
}
return options
}
open func update(_ handler: (() -> Void)? = nil) {
fetchResult = PHAsset.fetchAssets(in: assetList, options: PhotoKitAssetList.fetchOptions(mediaType))
public func update(handler: (() -> Void)? = nil) {
fetchResult = PHAsset.fetchAssetsInAssetCollection(assetList, options: PhotoKitAssetList.fetchOptions(mediaType))
if let handler = handler {
handler()
}
}
open subscript (index: Int) -> Item {
return Item(asset: fetchResult.object(at: index))
public subscript (index: Int) -> Item {
get {
guard let asset = fetchResult[index] as? PHAsset else {
fatalError("invalid index")
}
return Item(asset: asset)
}
}
// MARK: - CollectionType
open var startIndex: Int {
return 0
public var startIndex: Int {
get {
return 0
}
}
open var endIndex: Int {
return fetchResult.count
public var endIndex: Int {
get {
return fetchResult.count
}
}
}

View File

@ -16,46 +16,56 @@
import Foundation
class PickedAssetList: ItemList {
var assetlist: Array<Asset> = []
class PickedAssetList: ItemListType {
var assetlist: Array<AssetType> = []
weak var nohanaImagePickerController: NohanaImagePickerController?
// MARK: - ItemList
typealias Item = Asset
// MARK: - ItemListType
typealias Item = AssetType
var title: String {
return "Selected Assets"
get {
return "Selected Assets"
}
}
func update(_ handler:(() -> Void)?) {
func update(handler:(() -> Void)?) {
fatalError("not supported")
}
subscript (index: Int) -> Item {
return assetlist[index]
get {
return assetlist[index]
}
}
// MARK: - CollectionType
var startIndex: Int {
return 0
get {
return 0
}
}
var endIndex: Int {
return assetlist.count
get {
return assetlist.count
}
}
// MARK: - Manage assetlist
func pick(asset: Asset) -> Bool {
func pickAsset(asset: AssetType) -> Bool {
guard !isPicked(asset) 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), !canPick {
if let canPick = nohanaImagePickerController!.delegate?.nohanaImagePicker?(nohanaImagePickerController!, willPickPhotoKitAsset: (asset as! PhotoKitAsset).originalAsset, pickedAssetsCount: assetsCountBeforePicking)
where !canPick {
return false
}
}
@ -67,8 +77,8 @@ class PickedAssetList: ItemList {
if asset is PhotoKitAsset {
let originalAsset = (asset as! PhotoKitAsset).originalAsset
nohanaImagePickerController!.delegate?.nohanaImagePicker?(nohanaImagePickerController!, didPickPhotoKitAsset: originalAsset, pickedAssetsCount: assetsCountAfterPicking)
NotificationCenter.default.post(
Notification(
NSNotificationCenter.defaultCenter().postNotification(
NSNotification(
name: NotificationInfo.Asset.PhotoKit.didPick,
object: nohanaImagePickerController,
userInfo: [
@ -79,23 +89,23 @@ class PickedAssetList: ItemList {
)
}
return true
}
func drop(asset: Asset) -> Bool {
func dropAsset(asset: AssetType) -> Bool {
let assetsCountBeforeDropping = self.count
if asset is PhotoKitAsset {
if let canDrop = nohanaImagePickerController!.delegate?.nohanaImagePicker?(nohanaImagePickerController!, willDropPhotoKitAsset: (asset as! PhotoKitAsset).originalAsset, pickedAssetsCount: assetsCountBeforeDropping), !canDrop {
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 }
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)
NotificationCenter.default.post(
Notification(
NSNotificationCenter.defaultCenter().postNotification(
NSNotification(
name: NotificationInfo.Asset.PhotoKit.didDrop,
object: nohanaImagePickerController,
userInfo: [
@ -107,9 +117,9 @@ class PickedAssetList: ItemList {
}
return true
}
func isPicked(_ asset: Asset) -> Bool {
return assetlist.contains { $0.identifier == asset.identifier }
func isPicked(asset: AssetType) -> Bool {
return assetlist.contains{ $0.identifier == asset.identifier }
}
}
}

View File

@ -15,51 +15,41 @@
*/
struct Size {
static var statusBarHeight: CGFloat {
if UIApplication.shared.isStatusBarHidden {
return 0
get {
if UIApplication.sharedApplication().statusBarHidden {
return 0
}
return UIApplication.sharedApplication().statusBarFrame.size.height
}
return UIApplication.shared.statusBarFrame.size.height
}
static func navigationBarHeight(_ viewController: UIViewController) -> CGFloat {
static func navigationBarHeight(viewController: UIViewController) -> CGFloat {
return viewController.navigationController?.navigationBar.frame.size.height ?? CGFloat(0)
}
static func appBarHeight(_ viewController: UIViewController) -> CGFloat {
static func appBarHeight(viewController: UIViewController) -> CGFloat {
return statusBarHeight + navigationBarHeight(viewController)
}
static func toolbarHeight(_ viewController: UIViewController) -> CGFloat {
static func toolbarHeight(viewController: UIViewController) -> CGFloat {
guard let navigationController = viewController.navigationController else {
return 0
}
guard !navigationController.isToolbarHidden else {
guard !navigationController.toolbarHidden else {
return 0
}
return navigationController.toolbar.frame.size.height
}
static func screenRectWithoutAppBar(_ viewController: UIViewController) -> CGRect {
let appBarHeight: CGFloat = {
if #available(iOS 11.0, *) {
return viewController.view.safeAreaInsets.top
} else {
return Size.appBarHeight(viewController)
}
}()
let toolbarHeight: CGFloat = {
if #available(iOS 11.0, *) {
return viewController.view.safeAreaInsets.bottom
} else {
return Size.toolbarHeight(viewController)
}
}()
static func screenRectWithoutAppBar(viewController: UIViewController) -> CGRect {
let appBarHeight = Size.appBarHeight(viewController)
let toolbarHeight = Size.toolbarHeight(viewController)
return CGRect(
x: 0,
y: appBarHeight,
width: UIScreen.main.bounds.width,
height: UIScreen.main.bounds.height - appBarHeight - toolbarHeight)
width: UIScreen.mainScreen().bounds.width,
height: UIScreen.mainScreen().bounds.height - appBarHeight - toolbarHeight)
}
}

View File

@ -17,17 +17,16 @@
import UIKit
class SwipeInteractionController: UIPercentDrivenInteractiveTransition {
var viewController: UIViewController?
func attachToViewController(_ viewController: UIViewController) {
let count: Int? = viewController.navigationController?.viewControllers.count
guard count != nil && count! > 1 else {
func attachToViewController(viewController: UIViewController) {
guard viewController.navigationController?.viewControllers.count > 1 else {
return
}
let target = viewController.navigationController?.value(forKey: "_cachedInteractionController")
let gesture = UIScreenEdgePanGestureRecognizer(target: target, action: Selector(("handleNavigationTransition:")))
gesture.edges = .left
let target = viewController.navigationController?.valueForKey("_cachedInteractionController")
let gesture = UIScreenEdgePanGestureRecognizer(target: target, action: Selector("handleNavigationTransition:"))
gesture.edges = .Left
viewController.view.addGestureRecognizer(gesture)
}
}

View File

@ -1,4 +1,4 @@
<p align="center"><img src="./Images/logo.png" width="480" /></p>
<p align="center"><img src="./Images/logo.png" width="480" height="280" /></p>
## Description
@ -10,37 +10,33 @@ NohanaImagePicker enables your app to pick images from multiple album, and the m
## Usage
```swift
import UIKit
import Photos
```
import NohanaImagePicker
class MyViewController: UIViewController {
let picker = NohanaImagePickerController()
class ViewController: UIViewController, NohanaImagePickerControllerDelegate {
# override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.picker.delegate = self
present(self.picker, animated: true, completion: nil)
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(true)
let picker = NohanaImagePickerController()
picker.delegate = self
presentViewController(picker, animated: true, completion: nil)
}
}
extension MyViewController: NohanaImagePickerControllerDelegate {
func nohanaImagePickerDidCancel(_ picker: NohanaImagePickerController) {
func nohanaImagePickerDidCancel(picker: NohanaImagePickerController) {
print("🐷Canceled🙅")
picker.dismiss(animated: true, completion: nil)
picker.dismissViewControllerAnimated(true, completion: nil)
}
func nohanaImagePicker(_ picker: NohanaImagePickerController, didFinishPickingPhotoKitAssets pickedAssts :[PHAsset]) {
func nohanaImagePicker(picker: NohanaImagePickerController, didFinishPickingPhotoKitAssets pickedAssts :[PHAsset]) {
print("🐷Completed🙆\n\tpickedAssets = \(pickedAssts)")
picker.dismiss(animated: true, completion: nil)
picker.dismissViewControllerAnimated(true, completion: nil)
}
}
```
### Customize
```swift
```
let picker = NohanaImagePickerController()
// Set the maximum number of selectable images
@ -60,33 +56,41 @@ picker.shouldShowMoment = shouldShowEmptyAlbum = true
picker.shouldShowEmptyAlbum = true
// Disable to pick asset
picker.canPickAsset = { (asset:Asset) -> Bool in
picker.canPickAsset = { (asset:AssetType) -> Bool in
return false
}
// Color
ColorConfig.backgroundColor = UIColor.redColor()
```
## Requirements
- Swift 2.2 later
- iOS 8.0 later
- Swift2.2
- iOS8.0 later
## Installation
### Carthage
### Carthage (preferable)
Use [Carthage](https://github.com/Carthage/Carthage).
- Add `github "nohana/NohanaImagePicker"` to your Cartfile.
- If you want to use Swift3.0, add `github "nohana/NohanaImagePicker", "0.8.0"` instead.
- If you want to use Swift2.3, add `github "nohana/NohanaImagePicker", "0.6.1"` instead.
- If you want to use Swift2.2, add `github "nohana/NohanaImagePicker", "0.5.0"` instead.
- Run `carthage update`.
- Add following lines to your Info.plist:
```
<key>NSPhotoLibraryUsageDescription</key>
<string>To pick some photos.</string>
```
### Framework with CocoaPods
Use [CocoaPods](https://cocoapods.org/).
- Add the followings to your Podfile:
```ruby
use_frameworks!
pod "NohanaImagePicker"
```
- Run `pod install`.
## License