194 lines
7.6 KiB
Swift
194 lines
7.6 KiB
Swift
/*
|
||
Copyright (C) 2017 Apple Inc. All Rights Reserved.
|
||
See LICENSE.txt for this sample’s licensing information
|
||
|
||
Abstract:
|
||
Manages the top-level table view, a list of photo collections.
|
||
*/
|
||
|
||
|
||
import UIKit
|
||
import Photos
|
||
|
||
class MasterViewController: UITableViewController {
|
||
|
||
// MARK: Types for managing sections, cell and segue identifiers
|
||
enum Section: Int {
|
||
case allPhotos = 0
|
||
case smartAlbums
|
||
case userCollections
|
||
|
||
static let count = 3
|
||
}
|
||
|
||
enum CellIdentifier: String {
|
||
case allPhotos, collection
|
||
}
|
||
|
||
enum SegueIdentifier: String {
|
||
case showAllPhotos
|
||
case showCollection
|
||
}
|
||
|
||
// MARK: Properties
|
||
var allPhotos: PHFetchResult<PHAsset>!
|
||
var smartAlbums: PHFetchResult<PHAssetCollection>!
|
||
var userCollections: PHFetchResult<PHCollection>!
|
||
let sectionLocalizedTitles = ["", NSLocalizedString("Smart Albums", comment: ""), NSLocalizedString("Albums", comment: "")]
|
||
|
||
// MARK: UIViewController / Lifecycle
|
||
|
||
override func viewDidLoad() {
|
||
super.viewDidLoad()
|
||
|
||
let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(self.addAlbum))
|
||
self.navigationItem.rightBarButtonItem = addButton
|
||
|
||
|
||
// Create a PHFetchResult object for each section in the table view.
|
||
let allPhotosOptions = PHFetchOptions()
|
||
allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
|
||
allPhotos = PHAsset.fetchAssets(with: allPhotosOptions)
|
||
smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil)
|
||
userCollections = PHCollectionList.fetchTopLevelUserCollections(with: nil)
|
||
|
||
PHPhotoLibrary.shared().register(self)
|
||
|
||
}
|
||
|
||
deinit {
|
||
PHPhotoLibrary.shared().unregisterChangeObserver(self)
|
||
}
|
||
|
||
override func viewWillAppear(_ animated: Bool) {
|
||
self.clearsSelectionOnViewWillAppear = self.splitViewController!.isCollapsed
|
||
super.viewWillAppear(animated)
|
||
}
|
||
|
||
func addAlbum(_ sender: AnyObject) {
|
||
|
||
let alertController = UIAlertController(title: NSLocalizedString("New Album", comment: ""), message: nil, preferredStyle: .alert)
|
||
alertController.addTextField { textField in
|
||
textField.placeholder = NSLocalizedString("Album Name", comment: "")
|
||
}
|
||
|
||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Create", comment: ""), style: .default) { action in
|
||
let textField = alertController.textFields!.first!
|
||
if let title = textField.text, !title.isEmpty {
|
||
// Create a new album with the title entered.
|
||
PHPhotoLibrary.shared().performChanges({
|
||
PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: title)
|
||
}, completionHandler: { success, error in
|
||
if !success { print("error creating album: \(error)") }
|
||
})
|
||
}
|
||
})
|
||
self.present(alertController, animated: true, completion: nil)
|
||
}
|
||
|
||
|
||
// MARK: Segues
|
||
|
||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||
|
||
guard let destination = (segue.destination as? UINavigationController)?.topViewController as? AssetGridViewController
|
||
else { fatalError("unexpected view controller for segue") }
|
||
let cell = sender as! UITableViewCell
|
||
|
||
destination.title = cell.textLabel?.text
|
||
|
||
switch SegueIdentifier(rawValue: segue.identifier!)! {
|
||
case .showAllPhotos:
|
||
destination.fetchResult = allPhotos
|
||
case .showCollection:
|
||
|
||
// get the asset collection for the selected row
|
||
let indexPath = tableView.indexPath(for: cell)!
|
||
let collection: PHCollection
|
||
switch Section(rawValue: indexPath.section)! {
|
||
case .smartAlbums:
|
||
collection = smartAlbums.object(at: indexPath.row)
|
||
case .userCollections:
|
||
collection = userCollections.object(at: indexPath.row)
|
||
default: return // not reached; all photos section already handled by other segue
|
||
}
|
||
|
||
// configure the view controller with the asset collection
|
||
guard let assetCollection = collection as? PHAssetCollection
|
||
else { fatalError("expected asset collection") }
|
||
destination.fetchResult = PHAsset.fetchAssets(in: assetCollection, options: nil)
|
||
destination.assetCollection = assetCollection
|
||
}
|
||
}
|
||
|
||
// MARK: Table View
|
||
|
||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||
return Section.count
|
||
}
|
||
|
||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||
switch Section(rawValue: section)! {
|
||
case .allPhotos: return 1
|
||
case .smartAlbums: return smartAlbums.count
|
||
case .userCollections: return userCollections.count
|
||
}
|
||
}
|
||
|
||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||
switch Section(rawValue: indexPath.section)! {
|
||
case .allPhotos:
|
||
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier.allPhotos.rawValue, for: indexPath)
|
||
cell.textLabel!.text = NSLocalizedString("All Photos", comment: "")
|
||
return cell
|
||
|
||
case .smartAlbums:
|
||
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier.collection.rawValue, for: indexPath)
|
||
let collection = smartAlbums.object(at: indexPath.row)
|
||
cell.textLabel!.text = collection.localizedTitle
|
||
return cell
|
||
|
||
case .userCollections:
|
||
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier.collection.rawValue, for: indexPath)
|
||
let collection = userCollections.object(at: indexPath.row)
|
||
cell.textLabel!.text = collection.localizedTitle
|
||
return cell
|
||
}
|
||
}
|
||
|
||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||
return sectionLocalizedTitles[section]
|
||
}
|
||
|
||
}
|
||
|
||
// MARK: PHPhotoLibraryChangeObserver
|
||
extension MasterViewController: PHPhotoLibraryChangeObserver {
|
||
|
||
func photoLibraryDidChange(_ changeInstance: PHChange) {
|
||
// Change notifications may be made on a background queue. Re-dispatch to the
|
||
// main queue before acting on the change as we'll be updating the UI.
|
||
DispatchQueue.main.sync {
|
||
// Check each of the three top-level fetches for changes.
|
||
|
||
if let changeDetails = changeInstance.changeDetails(for: allPhotos) {
|
||
// Update the cached fetch result.
|
||
allPhotos = changeDetails.fetchResultAfterChanges
|
||
// (The table row for this one doesn't need updating, it always says "All Photos".)
|
||
}
|
||
|
||
// Update the cached fetch results, and reload the table sections to match.
|
||
if let changeDetails = changeInstance.changeDetails(for: smartAlbums) {
|
||
smartAlbums = changeDetails.fetchResultAfterChanges
|
||
tableView.reloadSections(IndexSet(integer: Section.smartAlbums.rawValue), with: .automatic)
|
||
}
|
||
if let changeDetails = changeInstance.changeDetails(for: userCollections) {
|
||
userCollections = changeDetails.fetchResultAfterChanges
|
||
tableView.reloadSections(IndexSet(integer: Section.userCollections.rawValue), with: .automatic)
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|