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,57 +522,22 @@ 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 // Store reference to current game state before we stop emulation so we can resume it if user decides to not load a save state
emulatorCore.save() { saveState in
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 let fileURL = FileManager.uniqueTemporaryURL()
if self.currentGameState == nil
{
emulatorCore.save() { saveState in
let fileURL = FileManager.uniqueTemporaryURL()
do
{
try FileManager.default.moveItem(at: saveState.fileURL, to: fileURL)
}
catch let error as NSError
{
print(error)
}
self.currentGameState = DeltaCore.SaveState(fileURL: fileURL, gameType: emulatorCore.game.type)
}
}
emulatorCore.stop()
emulationViewController.emulatorCore.start()
emulationViewController.emulatorCore.pause()
do do
{ {
try emulationViewController.emulatorCore.load(saveState) try FileManager.default.moveItem(at: saveState.fileURL, to: fileURL)
} self.currentGameState = DeltaCore.SaveState(fileURL: fileURL, gameType: emulatorCore.game.type)
catch EmulatorCore.SaveStateError.doesNotExist
{
print("Save State \(saveState.name) does not exist.")
} }
catch let error as NSError catch let error as NSError
{ {
@ -569,17 +545,52 @@ extension SaveStatesViewController: UIViewControllerPreviewingDelegate
} }
} }
return emulationViewController guard self.currentGameState != nil else { return }
emulatorCore.stop()
self.previewGameViewController.game = emulatorCore.game
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
{
try self.previewGameViewController.emulatorCore?.load(saveState)
return self.previewGameViewController
}
catch EmulatorCore.SaveStateError.doesNotExist
{
print("Save State \(saveState.name) does not exist.")
}
catch let error as NSError
{
print(error)
}
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> -