Compare commits
9 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
a10b65a739 | |
|
|
52bbdb08a7 | |
|
|
dba26e08f7 | |
|
|
fb874ac8a7 | |
|
|
c87637346f | |
|
|
6c3911f6a7 | |
|
|
4b3d2a40f8 | |
|
|
985be6cf63 | |
|
|
0f9f827bc6 |
|
|
@ -1 +1,2 @@
|
|||
4.2
|
||||
2.3
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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:.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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" : {
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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)")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,5 @@
|
|||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>To pick some photos.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1000"
|
||||
LastUpgradeVersion = "0800"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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())
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
|
@ -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"
|
||||
}
|
||||
],
|
||||
BIN
NohanaImagePicker/Images.xcassets/icon_photosize_alert_s.imageset/icon_photosize_alert_s@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
NohanaImagePicker/Images.xcassets/icon_photosize_alert_s.imageset/icon_photosize_alert_s@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
|
|
@ -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"
|
||||
}
|
||||
],
|
||||
BIN
NohanaImagePicker/Images.xcassets/icon_photosize_low_s.imageset/icon_photosize_low_s@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
NohanaImagePicker/Images.xcassets/icon_photosize_low_s.imageset/icon_photosize_low_s@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
|
|
@ -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>?
|
||||
}
|
||||
}
|
||||
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
64
README.md
|
|
@ -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
|
||||
|
||||
|
|
|
|||