mirror of
https://bitbucket.org/vendoo/vendoo_v1.0.git
synced 2025-12-25 19:57:41 +00:00
568 lines
24 KiB
Swift
568 lines
24 KiB
Swift
// The MIT License (MIT)
|
|
//
|
|
// Copyright (c) 2015 Joakim Gyllström
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
// copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
// SOFTWARE.
|
|
|
|
import UIKit
|
|
import Photos
|
|
import BSGridCollectionViewLayout
|
|
|
|
final class PhotosViewController : UICollectionViewController {
|
|
var selectionClosure: ((asset: PHAsset) -> Void)?
|
|
var deselectionClosure: ((asset: PHAsset) -> Void)?
|
|
var cancelClosure: ((assets: [PHAsset]) -> Void)?
|
|
var finishClosure: ((assets: [PHAsset]) -> Void)?
|
|
|
|
var doneBarButton: UIBarButtonItem?
|
|
var cancelBarButton: UIBarButtonItem?
|
|
var albumTitleView: AlbumTitleView?
|
|
|
|
let expandAnimator = ZoomAnimator()
|
|
let shrinkAnimator = ZoomAnimator()
|
|
|
|
private var photosDataSource: PhotoCollectionViewDataSource?
|
|
private var albumsDataSource: AlbumTableViewDataSource
|
|
private let cameraDataSource: CameraCollectionViewDataSource
|
|
private var composedDataSource: ComposedCollectionViewDataSource?
|
|
|
|
private var defaultSelections: PHFetchResult?
|
|
|
|
let settings: BSImagePickerSettings
|
|
|
|
private var doneBarButtonTitle: String?
|
|
|
|
lazy var albumsViewController: AlbumsViewController = {
|
|
let storyboard = UIStoryboard(name: "Albums", bundle: BSImagePickerViewController.bundle)
|
|
let vc = storyboard.instantiateInitialViewController() as! AlbumsViewController
|
|
vc.tableView.dataSource = self.albumsDataSource
|
|
vc.tableView.delegate = self
|
|
|
|
return vc
|
|
}()
|
|
|
|
private lazy var previewViewContoller: PreviewViewController? = {
|
|
return PreviewViewController(nibName: nil, bundle: nil)
|
|
}()
|
|
|
|
required init(fetchResults: [PHFetchResult], defaultSelections: PHFetchResult? = nil, settings aSettings: BSImagePickerSettings) {
|
|
albumsDataSource = AlbumTableViewDataSource(fetchResults: fetchResults)
|
|
cameraDataSource = CameraCollectionViewDataSource(settings: aSettings, cameraAvailable: UIImagePickerController.isSourceTypeAvailable(.Camera))
|
|
self.defaultSelections = defaultSelections
|
|
settings = aSettings
|
|
|
|
super.init(collectionViewLayout: GridCollectionViewLayout())
|
|
|
|
PHPhotoLibrary.sharedPhotoLibrary().registerChangeObserver(self)
|
|
}
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
fatalError("b0rk: initWithCoder not implemented")
|
|
}
|
|
|
|
deinit {
|
|
PHPhotoLibrary.sharedPhotoLibrary().unregisterChangeObserver(self)
|
|
}
|
|
|
|
override func loadView() {
|
|
super.loadView()
|
|
|
|
// Setup collection view
|
|
collectionView?.backgroundColor = UIColor.whiteColor()
|
|
collectionView?.allowsMultipleSelection = true
|
|
|
|
// Set an empty title to get < back button
|
|
title = " "
|
|
|
|
// Set button actions and add them to navigation item
|
|
doneBarButton?.target = self
|
|
doneBarButton?.action = #selector(PhotosViewController.doneButtonPressed(_:))
|
|
cancelBarButton?.target = self
|
|
cancelBarButton?.action = #selector(PhotosViewController.cancelButtonPressed(_:))
|
|
albumTitleView?.albumButton?.addTarget(self, action: #selector(PhotosViewController.albumButtonPressed(_:)), forControlEvents: .TouchUpInside)
|
|
navigationItem.leftBarButtonItem = cancelBarButton
|
|
navigationItem.rightBarButtonItem = doneBarButton
|
|
navigationItem.titleView = albumTitleView
|
|
|
|
if let album = albumsDataSource.fetchResults.first?.firstObject as? PHAssetCollection {
|
|
initializePhotosDataSource(album, selections: defaultSelections)
|
|
updateAlbumTitle(album)
|
|
synchronizeCollectionView()
|
|
}
|
|
|
|
// Add long press recognizer
|
|
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(PhotosViewController.collectionViewLongPressed(_:)))
|
|
longPressRecognizer.minimumPressDuration = 0.5
|
|
collectionView?.addGestureRecognizer(longPressRecognizer)
|
|
|
|
// Set navigation controller delegate
|
|
navigationController?.delegate = self
|
|
|
|
// Register cells
|
|
photosDataSource?.registerCellIdentifiersForCollectionView(collectionView)
|
|
cameraDataSource.registerCellIdentifiersForCollectionView(collectionView)
|
|
}
|
|
|
|
// MARK: Appear/Disappear
|
|
override func viewWillAppear(animated: Bool) {
|
|
super.viewWillAppear(animated)
|
|
|
|
updateDoneButton()
|
|
}
|
|
|
|
// MARK: Button actions
|
|
func cancelButtonPressed(sender: UIBarButtonItem) {
|
|
guard let closure = cancelClosure, let photosDataSource = photosDataSource else {
|
|
dismissViewControllerAnimated(true, completion: nil)
|
|
return
|
|
}
|
|
|
|
dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in
|
|
closure(assets: photosDataSource.selections)
|
|
})
|
|
|
|
dismissViewControllerAnimated(true, completion: nil)
|
|
}
|
|
|
|
func doneButtonPressed(sender: UIBarButtonItem) {
|
|
guard let closure = finishClosure, let photosDataSource = photosDataSource else {
|
|
dismissViewControllerAnimated(true, completion: nil)
|
|
return
|
|
}
|
|
|
|
dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in
|
|
closure(assets: photosDataSource.selections)
|
|
})
|
|
|
|
dismissViewControllerAnimated(true, completion: nil)
|
|
}
|
|
|
|
func albumButtonPressed(sender: UIButton) {
|
|
guard let popVC = albumsViewController.popoverPresentationController else {
|
|
return
|
|
}
|
|
|
|
popVC.permittedArrowDirections = .Up
|
|
popVC.sourceView = sender
|
|
let senderRect = sender.convertRect(sender.frame, fromView: sender.superview)
|
|
let sourceRect = CGRect(x: senderRect.origin.x, y: senderRect.origin.y + (sender.frame.size.height / 2), width: senderRect.size.width, height: senderRect.size.height)
|
|
popVC.sourceRect = sourceRect
|
|
popVC.delegate = self
|
|
albumsViewController.tableView.reloadData()
|
|
|
|
presentViewController(albumsViewController, animated: true, completion: nil)
|
|
}
|
|
|
|
func collectionViewLongPressed(sender: UIGestureRecognizer) {
|
|
if sender.state == .Began {
|
|
// Disable recognizer while we are figuring out location and pushing preview
|
|
sender.enabled = false
|
|
collectionView?.userInteractionEnabled = false
|
|
|
|
// Calculate which index path long press came from
|
|
let location = sender.locationInView(collectionView)
|
|
let indexPath = collectionView?.indexPathForItemAtPoint(location)
|
|
|
|
if let vc = previewViewContoller, let indexPath = indexPath, let cell = collectionView?.cellForItemAtIndexPath(indexPath) as? PhotoCell, let asset = cell.asset {
|
|
// Setup fetch options to be synchronous
|
|
let options = PHImageRequestOptions()
|
|
options.synchronous = true
|
|
|
|
// Load image for preview
|
|
if let imageView = vc.imageView {
|
|
PHCachingImageManager.defaultManager().requestImageForAsset(asset, targetSize:imageView.frame.size, contentMode: .AspectFit, options: options) { (result, _) in
|
|
imageView.image = result
|
|
}
|
|
}
|
|
|
|
// Setup animation
|
|
expandAnimator.sourceImageView = cell.imageView
|
|
expandAnimator.destinationImageView = vc.imageView
|
|
shrinkAnimator.sourceImageView = vc.imageView
|
|
shrinkAnimator.destinationImageView = cell.imageView
|
|
|
|
navigationController?.pushViewController(vc, animated: true)
|
|
}
|
|
|
|
// Re-enable recognizer, after animation is done
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(expandAnimator.transitionDuration(nil) * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), { () -> Void in
|
|
sender.enabled = true
|
|
self.collectionView?.userInteractionEnabled = true
|
|
})
|
|
}
|
|
}
|
|
|
|
// MARK: Private helper methods
|
|
func updateDoneButton() {
|
|
// Find right button
|
|
if let subViews = navigationController?.navigationBar.subviews, let photosDataSource = photosDataSource {
|
|
for view in subViews {
|
|
if let btn = view as? UIButton where checkIfRightButtonItem(btn) {
|
|
// Store original title if we havn't got it
|
|
if doneBarButtonTitle == nil {
|
|
doneBarButtonTitle = btn.titleForState(.Normal)
|
|
}
|
|
|
|
// Update title
|
|
if let doneBarButtonTitle = doneBarButtonTitle {
|
|
// Special case if we have selected 1 image and that is
|
|
// the max number of allowed selections
|
|
if (photosDataSource.selections.count == 1 && self.settings.maxNumberOfSelections == 1) {
|
|
btn.bs_setTitleWithoutAnimation("\(doneBarButtonTitle)", forState: .Normal)
|
|
} else if photosDataSource.selections.count > 0 {
|
|
btn.bs_setTitleWithoutAnimation("\(doneBarButtonTitle) (\(photosDataSource.selections.count))", forState: .Normal)
|
|
} else {
|
|
btn.bs_setTitleWithoutAnimation(doneBarButtonTitle, forState: .Normal)
|
|
}
|
|
|
|
// Enabled?
|
|
doneBarButton?.enabled = photosDataSource.selections.count > 0
|
|
}
|
|
|
|
// Stop loop
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check if a give UIButton is the right UIBarButtonItem in the navigation bar
|
|
// Somewhere along the road, our UIBarButtonItem gets transformed to an UINavigationButton
|
|
func checkIfRightButtonItem(btn: UIButton) -> Bool {
|
|
guard let rightButton = navigationItem.rightBarButtonItem else {
|
|
return false
|
|
}
|
|
|
|
// Store previous values
|
|
let wasRightEnabled = rightButton.enabled
|
|
let wasButtonEnabled = btn.enabled
|
|
|
|
// Set a known state for both buttons
|
|
rightButton.enabled = false
|
|
btn.enabled = false
|
|
|
|
// Change one and see if other also changes
|
|
rightButton.enabled = true
|
|
let isRightButton = btn.enabled
|
|
|
|
// Reset
|
|
rightButton.enabled = wasRightEnabled
|
|
btn.enabled = wasButtonEnabled
|
|
|
|
return isRightButton
|
|
}
|
|
|
|
func synchronizeSelectionInCollectionView(collectionView: UICollectionView) {
|
|
guard let photosDataSource = photosDataSource else {
|
|
return
|
|
}
|
|
|
|
// Get indexes of the selected assets
|
|
let mutableIndexSet = NSMutableIndexSet()
|
|
for object in photosDataSource.selections {
|
|
let index = photosDataSource.fetchResult.indexOfObject(object)
|
|
if index != NSNotFound {
|
|
mutableIndexSet.addIndex(index)
|
|
}
|
|
}
|
|
|
|
// Convert into index paths
|
|
let indexPaths = mutableIndexSet.bs_indexPathsForSection(1)
|
|
|
|
// Loop through them and set them as selected in the collection view
|
|
for indexPath in indexPaths {
|
|
collectionView.selectItemAtIndexPath(indexPath, animated: false, scrollPosition: .None)
|
|
}
|
|
}
|
|
|
|
func updateAlbumTitle(album: PHAssetCollection) {
|
|
if let title = album.localizedTitle {
|
|
// Update album title
|
|
albumTitleView?.albumTitle = title
|
|
}
|
|
}
|
|
|
|
func initializePhotosDataSource(album: PHAssetCollection, selections: PHFetchResult? = nil) {
|
|
// Set up a photo data source with album
|
|
let fetchOptions = PHFetchOptions()
|
|
fetchOptions.sortDescriptors = [
|
|
NSSortDescriptor(key: "creationDate", ascending: false)
|
|
]
|
|
fetchOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.Image.rawValue)
|
|
initializePhotosDataSourceWithFetchResult(PHAsset.fetchAssetsInAssetCollection(album, options: fetchOptions), selections: selections)
|
|
}
|
|
|
|
func initializePhotosDataSourceWithFetchResult(fetchResult: PHFetchResult, selections: PHFetchResult? = nil) {
|
|
let newDataSource = PhotoCollectionViewDataSource(fetchResult: fetchResult, selections: selections, settings: settings)
|
|
|
|
// Transfer image size
|
|
// TODO: Move image size to settings
|
|
if let photosDataSource = photosDataSource {
|
|
newDataSource.imageSize = photosDataSource.imageSize
|
|
newDataSource.selections = photosDataSource.selections
|
|
}
|
|
|
|
photosDataSource = newDataSource
|
|
|
|
// Hook up data source
|
|
composedDataSource = ComposedCollectionViewDataSource(dataSources: [cameraDataSource, newDataSource])
|
|
collectionView?.dataSource = composedDataSource
|
|
collectionView?.delegate = self
|
|
}
|
|
|
|
func synchronizeCollectionView() {
|
|
guard let collectionView = collectionView else {
|
|
return
|
|
}
|
|
|
|
// Reload and sync selections
|
|
collectionView.reloadData()
|
|
synchronizeSelectionInCollectionView(collectionView)
|
|
}
|
|
}
|
|
|
|
// MARK: UICollectionViewDelegate
|
|
extension PhotosViewController {
|
|
override func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool {
|
|
// Camera shouldn't be selected, but pop the UIImagePickerController!
|
|
if let composedDataSource = composedDataSource where composedDataSource.dataSources[indexPath.section].isEqual(cameraDataSource) {
|
|
let cameraController = UIImagePickerController()
|
|
cameraController.allowsEditing = false
|
|
cameraController.sourceType = .Camera
|
|
cameraController.delegate = self
|
|
|
|
self.presentViewController(cameraController, animated: true, completion: nil)
|
|
|
|
return false
|
|
}
|
|
|
|
return collectionView.userInteractionEnabled && photosDataSource!.selections.count < settings.maxNumberOfSelections
|
|
}
|
|
|
|
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
|
|
guard let photosDataSource = photosDataSource, let cell = collectionView.cellForItemAtIndexPath(indexPath) as? PhotoCell, let asset = photosDataSource.fetchResult.objectAtIndex(indexPath.row) as? PHAsset else {
|
|
return
|
|
}
|
|
|
|
// Select asset if not already selected
|
|
photosDataSource.selections.append(asset)
|
|
|
|
// Set selection number
|
|
if let selectionCharacter = settings.selectionCharacter {
|
|
cell.selectionString = String(selectionCharacter)
|
|
} else {
|
|
cell.selectionString = String(photosDataSource.selections.count)
|
|
}
|
|
|
|
// Update done button
|
|
updateDoneButton()
|
|
|
|
// Call selection closure
|
|
if let closure = selectionClosure {
|
|
dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in
|
|
closure(asset: asset)
|
|
})
|
|
}
|
|
}
|
|
|
|
override func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
|
|
guard let photosDataSource = photosDataSource, let asset = photosDataSource.fetchResult.objectAtIndex(indexPath.row) as? PHAsset, let index = photosDataSource.selections.indexOf(asset) else {
|
|
return
|
|
}
|
|
|
|
// Deselect asset
|
|
photosDataSource.selections.removeAtIndex(index)
|
|
|
|
// Update done button
|
|
updateDoneButton()
|
|
|
|
// Reload selected cells to update their selection number
|
|
if let selectedIndexPaths = collectionView.indexPathsForSelectedItems() {
|
|
UIView.setAnimationsEnabled(false)
|
|
collectionView.reloadItemsAtIndexPaths(selectedIndexPaths)
|
|
synchronizeSelectionInCollectionView(collectionView)
|
|
UIView.setAnimationsEnabled(true)
|
|
}
|
|
|
|
// Call deselection closure
|
|
if let closure = deselectionClosure {
|
|
dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in
|
|
closure(asset: asset)
|
|
})
|
|
}
|
|
}
|
|
|
|
override func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
|
|
guard let cell = cell as? CameraCell else {
|
|
return
|
|
}
|
|
|
|
cell.startLiveBackground() // Start live background
|
|
}
|
|
}
|
|
|
|
// MARK: UIPopoverPresentationControllerDelegate
|
|
extension PhotosViewController: UIPopoverPresentationControllerDelegate {
|
|
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
|
|
return .None
|
|
}
|
|
|
|
func popoverPresentationControllerShouldDismissPopover(popoverPresentationController: UIPopoverPresentationController) -> Bool {
|
|
return true
|
|
}
|
|
}
|
|
// MARK: UINavigationControllerDelegate
|
|
extension PhotosViewController: UINavigationControllerDelegate {
|
|
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
|
if operation == .Push {
|
|
return expandAnimator
|
|
} else {
|
|
return shrinkAnimator
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: UITableViewDelegate
|
|
extension PhotosViewController: UITableViewDelegate {
|
|
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
|
|
// Update photos data source
|
|
if let album = albumsDataSource.fetchResults[indexPath.section][indexPath.row] as? PHAssetCollection {
|
|
initializePhotosDataSource(album)
|
|
updateAlbumTitle(album)
|
|
synchronizeCollectionView()
|
|
}
|
|
|
|
// Dismiss album selection
|
|
albumsViewController.dismissViewControllerAnimated(true, completion: nil)
|
|
}
|
|
}
|
|
|
|
// MARK: Traits
|
|
extension PhotosViewController {
|
|
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
|
|
super.traitCollectionDidChange(previousTraitCollection)
|
|
|
|
if let collectionViewFlowLayout = collectionViewLayout as? GridCollectionViewLayout {
|
|
let itemSpacing: CGFloat = 2.0
|
|
let cellsPerRow = settings.cellsPerRow(verticalSize: traitCollection.verticalSizeClass, horizontalSize: traitCollection.horizontalSizeClass)
|
|
|
|
collectionViewFlowLayout.itemSpacing = itemSpacing
|
|
collectionViewFlowLayout.itemsPerRow = cellsPerRow
|
|
|
|
photosDataSource?.imageSize = collectionViewFlowLayout.itemSize
|
|
|
|
updateDoneButton()
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: UIImagePickerControllerDelegate
|
|
extension PhotosViewController: UIImagePickerControllerDelegate {
|
|
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
|
|
guard let image = info[UIImagePickerControllerOriginalImage] as? UIImage else {
|
|
picker.dismissViewControllerAnimated(true, completion: nil)
|
|
return
|
|
}
|
|
|
|
var placeholder: PHObjectPlaceholder?
|
|
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
|
|
let request = PHAssetChangeRequest.creationRequestForAssetFromImage(image)
|
|
placeholder = request.placeholderForCreatedAsset
|
|
}, completionHandler: { success, error in
|
|
guard let placeholder = placeholder, let asset = PHAsset.fetchAssetsWithLocalIdentifiers([placeholder.localIdentifier], options: nil).firstObject as? PHAsset where success == true else {
|
|
picker.dismissViewControllerAnimated(true, completion: nil)
|
|
return
|
|
}
|
|
|
|
dispatch_async(dispatch_get_main_queue()) {
|
|
// TODO: move to a function. this is duplicated in didSelect
|
|
self.photosDataSource?.selections.append(asset)
|
|
self.updateDoneButton()
|
|
|
|
// Call selection closure
|
|
if let closure = self.selectionClosure {
|
|
dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in
|
|
closure(asset: asset)
|
|
})
|
|
}
|
|
|
|
picker.dismissViewControllerAnimated(true, completion: nil)
|
|
}
|
|
})
|
|
}
|
|
|
|
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
|
|
picker.dismissViewControllerAnimated(true, completion: nil)
|
|
}
|
|
}
|
|
|
|
// MARK: PHPhotoLibraryChangeObserver
|
|
extension PhotosViewController: PHPhotoLibraryChangeObserver {
|
|
func photoLibraryDidChange(changeInstance: PHChange) {
|
|
guard let photosDataSource = photosDataSource, let collectionView = collectionView else {
|
|
return
|
|
}
|
|
|
|
dispatch_async(dispatch_get_main_queue(), { () -> Void in
|
|
if let photosChanges = changeInstance.changeDetailsForFetchResult(photosDataSource.fetchResult) {
|
|
// Update collection view
|
|
// Alright...we get spammed with change notifications, even when there are none. So guard against it
|
|
if photosChanges.hasIncrementalChanges && (photosChanges.removedIndexes?.count > 0 || photosChanges.insertedIndexes?.count > 0 || photosChanges.changedIndexes?.count > 0) {
|
|
// Update fetch result
|
|
photosDataSource.fetchResult = photosChanges.fetchResultAfterChanges
|
|
|
|
if let removed = photosChanges.removedIndexes {
|
|
collectionView.deleteItemsAtIndexPaths(removed.bs_indexPathsForSection(1))
|
|
}
|
|
|
|
if let inserted = photosChanges.insertedIndexes {
|
|
collectionView.insertItemsAtIndexPaths(inserted.bs_indexPathsForSection(1))
|
|
}
|
|
|
|
// Changes is causing issues right now...fix me later
|
|
// Example of issue:
|
|
// 1. Take a new photo
|
|
// 2. We will get a change telling to insert that asset
|
|
// 3. While it's being inserted we get a bunch of change request for that same asset
|
|
// 4. It flickers when reloading it while being inserted
|
|
// TODO: FIX
|
|
// if let changed = photosChanges.changedIndexes {
|
|
// print("changed")
|
|
// collectionView.reloadItemsAtIndexPaths(changed.bs_indexPathsForSection(1))
|
|
// }
|
|
|
|
// Sync selection
|
|
self.synchronizeSelectionInCollectionView(collectionView)
|
|
} else if photosChanges.hasIncrementalChanges == false {
|
|
// Update fetch result
|
|
photosDataSource.fetchResult = photosChanges.fetchResultAfterChanges
|
|
|
|
collectionView.reloadData()
|
|
|
|
// Sync selection
|
|
self.synchronizeSelectionInCollectionView(collectionView)
|
|
}
|
|
}
|
|
})
|
|
|
|
|
|
// TODO: Changes in albums
|
|
}
|
|
}
|