Shared/MasterViewController.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) |
} |
} |
} |
} |
Copyright © 2017 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2017-02-24