Improves SaveStatesViewController 3D Touch peeking performance

Pre-initializes GameViewController to ensure peek callback is fast
This commit is contained in:
Riley Testut 2016-07-17 16:21:28 -05:00
parent 3e02c36bcd
commit e827faadad

View File

@ -61,6 +61,9 @@ class SaveStatesViewController: UICollectionViewController
private let dateFormatter: DateFormatter private let dateFormatter: DateFormatter
private let previewGameViewController = GameViewController()
private var previewInteraction: UIPreviewInteraction!
required init?(coder aDecoder: NSCoder) required init?(coder aDecoder: NSCoder)
{ {
self.dateFormatter = DateFormatter() self.dateFormatter = DateFormatter()
@ -112,6 +115,12 @@ extension SaveStatesViewController
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(SaveStatesViewController.handleLongPressGesture(_:))) let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(SaveStatesViewController.handleLongPressGesture(_:)))
self.collectionView?.addGestureRecognizer(longPressGestureRecognizer) self.collectionView?.addGestureRecognizer(longPressGestureRecognizer)
// Pre-initialize previewGameViewController with game and start/pause emulation to ensure previewingContext(_:viewControllerForLocation:) callback doesn't take too long + break 3D Touch animation
self.preparePreviewGameViewController()
self.previewInteraction = UIPreviewInteraction(view: self.collectionView!)
self.previewInteraction.delegate = self
self.registerForPreviewing(with: self, sourceView: self.collectionView!) self.registerForPreviewing(with: self, sourceView: self.collectionView!)
self.updateBackgroundView() self.updateBackgroundView()
@ -414,6 +423,8 @@ private extension SaveStatesViewController
} }
} }
self.previewGameViewController.emulatorCore?.stop()
// Kinda hacky, but isMovingFromParentViewController only returns yes when popping off navigation controller, and not being dismissed modally // Kinda hacky, but isMovingFromParentViewController only returns yes when popping off navigation controller, and not being dismissed modally
// Because of this, this is only run when the user returns to PauseMenuViewController, and not when they choose a save state to load // Because of this, this is only run when the user returns to PauseMenuViewController, and not when they choose a save state to load
guard self.isMovingFromParentViewController() else { return } guard self.isMovingFromParentViewController() else { return }
@ -511,28 +522,14 @@ private extension SaveStatesViewController
} }
} }
//MARK: - <UIViewControllerPreviewingDelegate> - //MARK: - 3D Touch -
extension SaveStatesViewController: UIViewControllerPreviewingDelegate extension SaveStatesViewController: UIViewControllerPreviewingDelegate, UIPreviewInteractionDelegate
{ {
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? private func preparePreviewGameViewController()
{ {
guard let indexPath = self.collectionView?.indexPathForItem(at: location), layoutAttributes = self.collectionViewLayout.layoutAttributesForItem(at: indexPath) else { return nil }
previewingContext.sourceRect = layoutAttributes.frame
let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self) let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let saveState = self.fetchedResultsController.object(at: indexPath) as! SaveState
let emulationViewController = storyboard.instantiateViewController(withIdentifier: "emulationViewController") as! EmulationViewController
emulationViewController.game = emulatorCore.game as! Game
emulationViewController.overridePreviewActionItems = self.actionsForSaveState(saveState).filter{ $0.style != .cancel }.map{ $0.previewAction }
emulationViewController.deferredPreparationHandler = { [unowned emulationViewController] in
// Store reference to current game state before we stop emulation so we can resume it if user decides to not load a save state // Store reference to current game state before we stop emulation so we can resume it if user decides to not load a save state
if self.currentGameState == nil
{
emulatorCore.save() { saveState in emulatorCore.save() { saveState in
let fileURL = FileManager.uniqueTemporaryURL() let fileURL = FileManager.uniqueTemporaryURL()
@ -540,24 +537,39 @@ extension SaveStatesViewController: UIViewControllerPreviewingDelegate
do do
{ {
try FileManager.default.moveItem(at: saveState.fileURL, to: fileURL) try FileManager.default.moveItem(at: saveState.fileURL, to: fileURL)
self.currentGameState = DeltaCore.SaveState(fileURL: fileURL, gameType: emulatorCore.game.type)
} }
catch let error as NSError catch let error as NSError
{ {
print(error) print(error)
} }
}
self.currentGameState = DeltaCore.SaveState(fileURL: fileURL, gameType: emulatorCore.game.type) guard self.currentGameState != nil else { return }
}
}
emulatorCore.stop() emulatorCore.stop()
emulationViewController.emulatorCore.start() self.previewGameViewController.game = emulatorCore.game
emulationViewController.emulatorCore.pause() self.previewGameViewController.emulatorCore?.start()
self.previewGameViewController.emulatorCore?.pause()
}
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?
{
guard
let indexPath = self.collectionView?.indexPathForItem(at: location),
let layoutAttributes = self.collectionViewLayout.layoutAttributesForItem(at: indexPath)
where self.currentGameState != nil
else { return nil }
previewingContext.sourceRect = layoutAttributes.frame
let saveState = self.fetchedResultsController.object(at: indexPath) as! SaveState
do do
{ {
try emulationViewController.emulatorCore.load(saveState) try self.previewGameViewController.emulatorCore?.load(saveState)
return self.previewGameViewController
} }
catch EmulatorCore.SaveStateError.doesNotExist catch EmulatorCore.SaveStateError.doesNotExist
{ {
@ -567,19 +579,18 @@ extension SaveStatesViewController: UIViewControllerPreviewingDelegate
{ {
print(error) print(error)
} }
}
return emulationViewController return nil
} }
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController)
{ {
let emulationViewController = viewControllerToCommit as! EmulationViewController let gameViewController = viewControllerToCommit as! GameViewController
emulationViewController.emulatorCore.pause() gameViewController.emulatorCore?.pause()
emulationViewController.emulatorCore.save() { saveState in gameViewController.emulatorCore?.save() { saveState in
emulationViewController.emulatorCore.stop() gameViewController.emulatorCore?.stop()
let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self) let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self)
@ -593,6 +604,15 @@ extension SaveStatesViewController: UIViewControllerPreviewingDelegate
emulatorCore.videoManager.enabled = true emulatorCore.videoManager.enabled = true
} }
} }
func previewInteraction(_ previewInteraction: UIPreviewInteraction, didUpdatePreviewTransition transitionProgress: CGFloat, ended: Bool)
{
}
func previewInteractionDidCancel(_ previewInteraction: UIPreviewInteraction)
{
self.previewGameViewController.emulatorCore?.pause()
}
} }
//MARK: - <UICollectionViewDataSource> - //MARK: - <UICollectionViewDataSource> -