PhotoProgress/PhotosViewController.swift
/* |
Copyright (C) 2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
PhotosViewController is our root UIViewController which is responsible for showing the overall progress and a tool bar. |
*/ |
import UIKit |
/** |
The KVO context used for all `PhotosViewController` instances. This provides a stable |
address to use as the context parameter for the KVO observation methods. |
*/ |
private var photosViewControllerObservationContext = 0 |
class PhotosViewController: UIViewController { |
// MARK: Properties |
/// The album that the app is importing |
fileprivate var album: Album? |
/// Keys that we observe on `overallProgress`. |
fileprivate let overalProgressObservedKeys = [ |
"fractionCompleted", |
"completedUnitCount", |
"totalUnitCount", |
"cancelled", |
"paused" |
] |
/// The overall progress for the import that is shown to the user |
fileprivate var overallProgress: Progress? { |
willSet { |
guard let formerProgress = overallProgress else { return } |
for overalProgressObservedKey in overalProgressObservedKeys { |
formerProgress.removeObserver(self, forKeyPath: overalProgressObservedKey, context: &photosViewControllerObservationContext) |
} |
} |
didSet { |
if let newProgress = overallProgress { |
for overalProgressObservedKey in overalProgressObservedKeys { |
newProgress.addObserver(self, forKeyPath: overalProgressObservedKey, options: [], context: &photosViewControllerObservationContext) |
} |
} |
updateProgressView() |
updateToolbar() |
} |
} |
fileprivate var progressViewIsHidden = true |
fileprivate var overallProgressIsFinished: Bool { |
let completed = overallProgress!.completedUnitCount |
let total = overallProgress!.totalUnitCount |
// An NSProgress is finished if it's not indeterminate, and the completedUnitCount > totalUnitCount. |
return (completed >= total && total > 0 && completed > 0) || (completed > 0 && total == 0) |
} |
// MARK: IBOutlets |
@IBOutlet var progressView: UIProgressView! |
@IBOutlet var progressContainerView: UIView! |
@IBOutlet var startToolbarItem: UIBarButtonItem! |
@IBOutlet var cancelToolbarItem: UIBarButtonItem! |
@IBOutlet var pauseToolbarItem: UIBarButtonItem! |
@IBOutlet var resumeToolbarItem: UIBarButtonItem! |
@IBOutlet var resetToolbarItem: UIBarButtonItem! |
// MARK: IBActions |
@IBAction func startImport() { |
overallProgress = album?.importPhotos() |
} |
@IBAction func cancelImport() { |
overallProgress?.cancel() |
} |
@IBAction func pauseImport() { |
overallProgress?.pause() |
} |
@IBAction func resumeImport() { |
overallProgress?.resume() |
} |
@IBAction func resetImport() { |
album?.resetPhotos() |
overallProgress = nil |
} |
// MARK: Key-Value Observing |
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) { |
guard context == &photosViewControllerObservationContext else { |
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) |
return |
} |
OperationQueue.main.addOperation { |
self.updateProgressView() |
self.updateToolbar() |
} |
} |
// MARK: Update UI |
fileprivate func updateProgressView() { |
let shouldHide: Bool |
if let overallProgress = self.overallProgress { |
shouldHide = overallProgressIsFinished || overallProgress.isCancelled |
progressView.progress = Float(overallProgress.fractionCompleted) |
} |
else { |
shouldHide = true |
} |
if progressViewIsHidden != shouldHide { |
UIView.animate(withDuration: 0.2, animations: { |
self.progressContainerView.alpha = shouldHide ? 0.0 : 1.0 |
}) |
progressViewIsHidden = shouldHide |
} |
} |
fileprivate func updateToolbar() { |
var items = [UIBarButtonItem]() |
if let overallProgress = overallProgress { |
if overallProgressIsFinished || overallProgress.isCancelled { |
items.append(resetToolbarItem) |
} |
else { |
// The import is running. |
items.append(cancelToolbarItem) |
if overallProgress.isPaused { |
items.append(resumeToolbarItem) |
} |
else { |
items.append(pauseToolbarItem) |
} |
} |
} |
else { |
items.append(startToolbarItem) |
} |
navigationController?.toolbar?.setItems(items, animated: true) |
} |
// MARK: Nib Loading |
override func awakeFromNib() { |
album = Album() |
} |
// MARK: Segue Handling |
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { |
if segue.identifier == "collectionView" { |
if let collectionViewController = segue.destination as? PhotosCollectionViewController { |
collectionViewController.album = album |
} |
} |
} |
} |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-10-04