Adds support for Locked Save States
This commit is contained in:
parent
0b12732e6e
commit
aa4f5fb532
@ -49,6 +49,8 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
|
|||||||
|
|
||||||
for (index, attributes) in layoutAttributes.enumerate()
|
for (index, attributes) in layoutAttributes.enumerate()
|
||||||
{
|
{
|
||||||
|
guard attributes.representedElementCategory == .Cell else { continue }
|
||||||
|
|
||||||
// Ensure equal spacing between items (that also match the section insets)
|
// Ensure equal spacing between items (that also match the section insets)
|
||||||
if index > 0
|
if index > 0
|
||||||
{
|
{
|
||||||
|
|||||||
@ -42,6 +42,7 @@
|
|||||||
<attribute name="identifier" attributeType="String" syncable="YES"/>
|
<attribute name="identifier" attributeType="String" syncable="YES"/>
|
||||||
<attribute name="modifiedDate" attributeType="Date" syncable="YES"/>
|
<attribute name="modifiedDate" attributeType="Date" syncable="YES"/>
|
||||||
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
|
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
|
||||||
|
<attribute name="type" attributeType="Integer 16" defaultValueString="1" syncable="YES"/>
|
||||||
<relationship name="game" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Game" inverseName="saveStates" inverseEntity="Game" syncable="YES"/>
|
<relationship name="game" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Game" inverseName="saveStates" inverseEntity="Game" syncable="YES"/>
|
||||||
<uniquenessConstraints>
|
<uniquenessConstraints>
|
||||||
<uniquenessConstraint>
|
<uniquenessConstraint>
|
||||||
@ -52,6 +53,6 @@
|
|||||||
<elements>
|
<elements>
|
||||||
<element name="Game" positionX="-200" positionY="-72" width="128" height="148"/>
|
<element name="Game" positionX="-200" positionY="-72" width="128" height="148"/>
|
||||||
<element name="GameCollection" positionX="-198" positionY="-207" width="128" height="90"/>
|
<element name="GameCollection" positionX="-198" positionY="-207" width="128" height="90"/>
|
||||||
<element name="SaveState" positionX="-198" positionY="113" width="128" height="135"/>
|
<element name="SaveState" positionX="-198" positionY="113" width="128" height="150"/>
|
||||||
</elements>
|
</elements>
|
||||||
</model>
|
</model>
|
||||||
@ -20,9 +20,17 @@ extension SaveState
|
|||||||
case name
|
case name
|
||||||
case creationDate
|
case creationDate
|
||||||
case modifiedDate
|
case modifiedDate
|
||||||
|
case type
|
||||||
|
|
||||||
case game
|
case game
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc enum Type: Int16
|
||||||
|
{
|
||||||
|
case Auto
|
||||||
|
case General
|
||||||
|
case Locked
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc(SaveState)
|
@objc(SaveState)
|
||||||
@ -30,6 +38,7 @@ class SaveState: NSManagedObject, SaveStateType
|
|||||||
{
|
{
|
||||||
@NSManaged var name: String?
|
@NSManaged var name: String?
|
||||||
@NSManaged var modifiedDate: NSDate
|
@NSManaged var modifiedDate: NSDate
|
||||||
|
@NSManaged var type: Type
|
||||||
|
|
||||||
@NSManaged private(set) var filename: String
|
@NSManaged private(set) var filename: String
|
||||||
@NSManaged private(set) var identifier: String
|
@NSManaged private(set) var identifier: String
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
BF2A53FC1BB74FC10052BD0C /* SNESDeltaCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BFC134E01AAD82460087AD7B /* SNESDeltaCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
BF2A53FC1BB74FC10052BD0C /* SNESDeltaCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BFC134E01AAD82460087AD7B /* SNESDeltaCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
BF2A53FD1BB74FC60052BD0C /* ZipZap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF70798B1B6B464B0019077C /* ZipZap.framework */; };
|
BF2A53FD1BB74FC60052BD0C /* ZipZap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF70798B1B6B464B0019077C /* ZipZap.framework */; };
|
||||||
BF2A53FE1BB74FC60052BD0C /* ZipZap.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BF70798B1B6B464B0019077C /* ZipZap.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
BF2A53FE1BB74FC60052BD0C /* ZipZap.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BF70798B1B6B464B0019077C /* ZipZap.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
|
BF2B98E61C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF2B98E51C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift */; };
|
||||||
BF353FF21C5D7FB000C1184C /* PauseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF353FF11C5D7FB000C1184C /* PauseViewController.swift */; };
|
BF353FF21C5D7FB000C1184C /* PauseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF353FF11C5D7FB000C1184C /* PauseViewController.swift */; };
|
||||||
BF353FF31C5D7FB000C1184C /* PauseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF353FF11C5D7FB000C1184C /* PauseViewController.swift */; };
|
BF353FF31C5D7FB000C1184C /* PauseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF353FF11C5D7FB000C1184C /* PauseViewController.swift */; };
|
||||||
BF353FF61C5D837600C1184C /* PauseMenu.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BF353FF41C5D837600C1184C /* PauseMenu.storyboard */; };
|
BF353FF61C5D837600C1184C /* PauseMenu.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BF353FF41C5D837600C1184C /* PauseMenu.storyboard */; };
|
||||||
@ -136,6 +137,7 @@
|
|||||||
BF27CC901BCB156200A20D89 /* EmulationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmulationViewController.swift; sourceTree = "<group>"; };
|
BF27CC901BCB156200A20D89 /* EmulationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmulationViewController.swift; sourceTree = "<group>"; };
|
||||||
BF27CC941BCB7B7A00A20D89 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; };
|
BF27CC941BCB7B7A00A20D89 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
BF27CC961BCC890700A20D89 /* GamesCollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GamesCollectionViewController.swift; sourceTree = "<group>"; };
|
BF27CC961BCC890700A20D89 /* GamesCollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GamesCollectionViewController.swift; sourceTree = "<group>"; };
|
||||||
|
BF2B98E51C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SaveStatesCollectionHeaderView.swift; path = "Pause Menu/Save States/SaveStatesCollectionHeaderView.swift"; sourceTree = "<group>"; };
|
||||||
BF353FF11C5D7FB000C1184C /* PauseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PauseViewController.swift; path = "Pause Menu/PauseViewController.swift"; sourceTree = "<group>"; };
|
BF353FF11C5D7FB000C1184C /* PauseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PauseViewController.swift; path = "Pause Menu/PauseViewController.swift"; sourceTree = "<group>"; };
|
||||||
BF353FF51C5D837600C1184C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/PauseMenu.storyboard; sourceTree = "<group>"; };
|
BF353FF51C5D837600C1184C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/PauseMenu.storyboard; sourceTree = "<group>"; };
|
||||||
BF353FF81C5D870B00C1184C /* PauseItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PauseItem.swift; path = "Pause Menu/PauseItem.swift"; sourceTree = "<group>"; };
|
BF353FF81C5D870B00C1184C /* PauseItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PauseItem.swift; path = "Pause Menu/PauseItem.swift"; sourceTree = "<group>"; };
|
||||||
@ -242,6 +244,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
BF3540041C5DA70400C1184C /* SaveStatesViewController.swift */,
|
BF3540041C5DA70400C1184C /* SaveStatesViewController.swift */,
|
||||||
|
BF2B98E51C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift */,
|
||||||
);
|
);
|
||||||
name = "Save States";
|
name = "Save States";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -714,6 +717,7 @@
|
|||||||
BFDE393C1BC0CEDF003F72E8 /* Game.swift in Sources */,
|
BFDE393C1BC0CEDF003F72E8 /* Game.swift in Sources */,
|
||||||
BFC2731A1BE6152200D22B05 /* GameCollection.swift in Sources */,
|
BFC2731A1BE6152200D22B05 /* GameCollection.swift in Sources */,
|
||||||
BFF1E5641BE04CAF000E9EF6 /* BoxArtImageView.swift in Sources */,
|
BFF1E5641BE04CAF000E9EF6 /* BoxArtImageView.swift in Sources */,
|
||||||
|
BF2B98E61C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift in Sources */,
|
||||||
BF762EAB1BC1B076002C8866 /* NSManagedObject+Conveniences.swift in Sources */,
|
BF762EAB1BC1B076002C8866 /* NSManagedObject+Conveniences.swift in Sources */,
|
||||||
BF353FFF1C5DA3C500C1184C /* PausePresentationController.swift in Sources */,
|
BF353FFF1C5DA3C500C1184C /* PausePresentationController.swift in Sources */,
|
||||||
BF7AE80A1C2E8C7600B1B5BC /* UIColor+Delta.swift in Sources */,
|
BF7AE80A1C2E8C7600B1B5BC /* UIColor+Delta.swift in Sources */,
|
||||||
|
|||||||
@ -150,13 +150,13 @@
|
|||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||||
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="20" minimumInteritemSpacing="20" id="tvW-q1-PD8" customClass="GridCollectionViewLayout" customModule="Delta" customModuleProvider="target">
|
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="20" minimumInteritemSpacing="20" id="tvW-q1-PD8" customClass="GridCollectionViewLayout" customModule="Delta" customModuleProvider="target">
|
||||||
<size key="itemSize" width="50" height="50"/>
|
<size key="itemSize" width="50" height="50"/>
|
||||||
<size key="headerReferenceSize" width="0.0" height="0.0"/>
|
<size key="headerReferenceSize" width="50" height="50"/>
|
||||||
<size key="footerReferenceSize" width="0.0" height="0.0"/>
|
<size key="footerReferenceSize" width="0.0" height="0.0"/>
|
||||||
<inset key="sectionInset" minX="20" minY="20" maxX="20" maxY="20"/>
|
<inset key="sectionInset" minX="20" minY="10" maxX="20" maxY="20"/>
|
||||||
</collectionViewFlowLayout>
|
</collectionViewFlowLayout>
|
||||||
<cells>
|
<cells>
|
||||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="Cell" id="c3N-1A-ryV" customClass="GridCollectionViewCell" customModule="Delta" customModuleProvider="target">
|
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="Cell" id="c3N-1A-ryV" customClass="GridCollectionViewCell" customModule="Delta" customModuleProvider="target">
|
||||||
<rect key="frame" x="20" y="84" width="50" height="50"/>
|
<rect key="frame" x="20" y="124" width="50" height="50"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
|
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
|
||||||
@ -165,6 +165,10 @@
|
|||||||
</view>
|
</view>
|
||||||
</collectionViewCell>
|
</collectionViewCell>
|
||||||
</cells>
|
</cells>
|
||||||
|
<collectionReusableView key="sectionHeaderView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="Header" id="YeY-W9-CC6" customClass="SaveStatesCollectionHeaderView" customModule="Delta" customModuleProvider="target">
|
||||||
|
<rect key="frame" x="0.0" y="64" width="600" height="50"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
</collectionReusableView>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="dataSource" destination="OOk-k7-INg" id="8l7-6Q-tQp"/>
|
<outlet property="dataSource" destination="OOk-k7-INg" id="8l7-6Q-tQp"/>
|
||||||
<outlet property="delegate" destination="OOk-k7-INg" id="aLg-5i-MAd"/>
|
<outlet property="delegate" destination="OOk-k7-INg" id="aLg-5i-MAd"/>
|
||||||
|
|||||||
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// SaveStatesCollectionHeaderView.swift
|
||||||
|
// Delta
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 3/15/16.
|
||||||
|
// Copyright © 2016 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SaveStatesCollectionHeaderView: UICollectionReusableView
|
||||||
|
{
|
||||||
|
let textLabel = UILabel()
|
||||||
|
|
||||||
|
override init(frame: CGRect)
|
||||||
|
{
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
self.initialize()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder)
|
||||||
|
{
|
||||||
|
super.init(coder: aDecoder)
|
||||||
|
|
||||||
|
self.initialize()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func initialize()
|
||||||
|
{
|
||||||
|
self.textLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
self.textLabel.textColor = UIColor.whiteColor()
|
||||||
|
|
||||||
|
var fontDescriptor = UIFontDescriptor.preferredFontDescriptorWithTextStyle(UIFontTextStyleTitle3)
|
||||||
|
fontDescriptor = fontDescriptor.fontDescriptorWithSymbolicTraits([.TraitBold])
|
||||||
|
|
||||||
|
self.textLabel.font = UIFont(descriptor: fontDescriptor, size: 0.0)
|
||||||
|
self.textLabel.textAlignment = .Center
|
||||||
|
self.addSubview(self.textLabel)
|
||||||
|
|
||||||
|
// Auto Layout
|
||||||
|
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[textLabel]-20-|", options: [], metrics: nil, views: ["textLabel": self.textLabel]))
|
||||||
|
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-10-[textLabel]|", options: [], metrics: nil, views: ["textLabel": self.textLabel]))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -26,6 +26,13 @@ extension SaveStatesViewController
|
|||||||
case Saving
|
case Saving
|
||||||
case Loading
|
case Loading
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Section: Int
|
||||||
|
{
|
||||||
|
case Auto
|
||||||
|
case General
|
||||||
|
case Locked
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SaveStatesViewController: UICollectionViewController
|
class SaveStatesViewController: UICollectionViewController
|
||||||
@ -42,6 +49,7 @@ class SaveStatesViewController: UICollectionViewController
|
|||||||
|
|
||||||
private var prototypeCell = GridCollectionViewCell()
|
private var prototypeCell = GridCollectionViewCell()
|
||||||
private var prototypeCellWidthConstraint: NSLayoutConstraint!
|
private var prototypeCellWidthConstraint: NSLayoutConstraint!
|
||||||
|
private var prototypeHeader = SaveStatesCollectionHeaderView()
|
||||||
|
|
||||||
private var fetchedResultsController: NSFetchedResultsController!
|
private var fetchedResultsController: NSFetchedResultsController!
|
||||||
|
|
||||||
@ -140,9 +148,9 @@ private extension SaveStatesViewController
|
|||||||
let fetchRequest = SaveState.fetchRequest()
|
let fetchRequest = SaveState.fetchRequest()
|
||||||
fetchRequest.returnsObjectsAsFaults = false
|
fetchRequest.returnsObjectsAsFaults = false
|
||||||
fetchRequest.predicate = NSPredicate(format: "%K == %@", SaveState.Attributes.game.rawValue, game)
|
fetchRequest.predicate = NSPredicate(format: "%K == %@", SaveState.Attributes.game.rawValue, game)
|
||||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: SaveState.Attributes.creationDate.rawValue, ascending: true)]
|
fetchRequest.sortDescriptors = [NSSortDescriptor(key: SaveState.Attributes.type.rawValue, ascending: true), NSSortDescriptor(key: SaveState.Attributes.creationDate.rawValue, ascending: true)]
|
||||||
|
|
||||||
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
|
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: SaveState.Attributes.type.rawValue, cacheName: nil)
|
||||||
self.fetchedResultsController.delegate = self
|
self.fetchedResultsController.delegate = self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +166,7 @@ private extension SaveStatesViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - Configure Cell -
|
//MARK: - Configure Views -
|
||||||
|
|
||||||
func configureCollectionViewCell(cell: GridCollectionViewCell, forIndexPath indexPath: NSIndexPath, ignoreExpensiveOperations ignoreOperations: Bool = false)
|
func configureCollectionViewCell(cell: GridCollectionViewCell, forIndexPath indexPath: NSIndexPath, ignoreExpensiveOperations ignoreOperations: Bool = false)
|
||||||
{
|
{
|
||||||
@ -175,6 +183,7 @@ private extension SaveStatesViewController
|
|||||||
|
|
||||||
if let image = image
|
if let image = image
|
||||||
{
|
{
|
||||||
|
cell.imageView.backgroundColor = nil
|
||||||
cell.imageView.image = image
|
cell.imageView.image = image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,6 +206,22 @@ private extension SaveStatesViewController
|
|||||||
cell.textLabel.text = name
|
cell.textLabel.text = name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func configureCollectionViewHeaderView(headerView: SaveStatesCollectionHeaderView, forSection section: Int)
|
||||||
|
{
|
||||||
|
let section = self.correctedSectionForSectionIndex(section)
|
||||||
|
|
||||||
|
let title: String
|
||||||
|
|
||||||
|
switch section
|
||||||
|
{
|
||||||
|
case .Auto: title = NSLocalizedString("Auto Save", comment: "")
|
||||||
|
case .General: title = NSLocalizedString("General", comment: "")
|
||||||
|
case .Locked: title = NSLocalizedString("Locked", comment: "")
|
||||||
|
}
|
||||||
|
|
||||||
|
headerView.textLabel.text = title
|
||||||
|
}
|
||||||
|
|
||||||
//MARK: - Gestures -
|
//MARK: - Gestures -
|
||||||
|
|
||||||
@objc func handleLongPressGesture(gestureRecognizer: UILongPressGestureRecognizer)
|
@objc func handleLongPressGesture(gestureRecognizer: UILongPressGestureRecognizer)
|
||||||
@ -205,12 +230,29 @@ private extension SaveStatesViewController
|
|||||||
|
|
||||||
guard let indexPath = self.collectionView?.indexPathForItemAtPoint(gestureRecognizer.locationInView(self.collectionView)) else { return }
|
guard let indexPath = self.collectionView?.indexPathForItemAtPoint(gestureRecognizer.locationInView(self.collectionView)) else { return }
|
||||||
|
|
||||||
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
|
|
||||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Delete Save State", comment: ""), style: .Destructive, handler: { action in
|
|
||||||
let saveState = self.fetchedResultsController.objectAtIndexPath(indexPath) as! SaveState
|
let saveState = self.fetchedResultsController.objectAtIndexPath(indexPath) as! SaveState
|
||||||
|
|
||||||
|
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
|
||||||
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil))
|
||||||
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("Delete Save State", comment: ""), style: .Destructive, handler: { action in
|
||||||
self.deleteSaveState(saveState)
|
self.deleteSaveState(saveState)
|
||||||
}))
|
}))
|
||||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil))
|
|
||||||
|
let section = self.correctedSectionForSectionIndex(indexPath.section)
|
||||||
|
switch section
|
||||||
|
{
|
||||||
|
case .Auto: break
|
||||||
|
case .General:
|
||||||
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("Lock Save State", comment: ""), style: .Default, handler: { action in
|
||||||
|
self.lockSaveState(saveState)
|
||||||
|
}))
|
||||||
|
|
||||||
|
case .Locked:
|
||||||
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("Unlock Save State", comment: ""), style: .Default, handler: { action in
|
||||||
|
self.unlockSaveState(saveState)
|
||||||
|
}))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
self.presentViewController(alertController, animated: true, completion: nil)
|
self.presentViewController(alertController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
@ -261,11 +303,48 @@ private extension SaveStatesViewController
|
|||||||
|
|
||||||
self.presentViewController(confirmationAlertController, animated: true, completion: nil)
|
self.presentViewController(confirmationAlertController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func lockSaveState(saveState: SaveState)
|
||||||
|
{
|
||||||
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
|
backgroundContext.performBlockAndWait() {
|
||||||
|
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState
|
||||||
|
temporarySaveState.type = .Locked
|
||||||
|
backgroundContext.saveWithErrorLogging()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unlockSaveState(saveState: SaveState)
|
||||||
|
{
|
||||||
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
|
backgroundContext.performBlockAndWait() {
|
||||||
|
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState
|
||||||
|
temporarySaveState.type = .General
|
||||||
|
backgroundContext.saveWithErrorLogging()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - Convenience Methods -
|
||||||
|
|
||||||
|
func correctedSectionForSectionIndex(section: Int) -> Section
|
||||||
|
{
|
||||||
|
let sectionInfo = self.fetchedResultsController.sections![section]
|
||||||
|
let sectionIndex = Int(sectionInfo.name)!
|
||||||
|
|
||||||
|
let section = Section(rawValue: sectionIndex)!
|
||||||
|
return section
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - <UICollectionViewDataSource> -
|
//MARK: - <UICollectionViewDataSource> -
|
||||||
extension SaveStatesViewController
|
extension SaveStatesViewController
|
||||||
{
|
{
|
||||||
|
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
|
||||||
|
{
|
||||||
|
let numberOfSections = self.fetchedResultsController.sections!.count
|
||||||
|
return numberOfSections
|
||||||
|
}
|
||||||
|
|
||||||
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
|
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
|
||||||
{
|
{
|
||||||
let section = self.fetchedResultsController.sections![section]
|
let section = self.fetchedResultsController.sections![section]
|
||||||
@ -278,6 +357,13 @@ extension SaveStatesViewController
|
|||||||
self.configureCollectionViewCell(cell, forIndexPath: indexPath)
|
self.configureCollectionViewCell(cell, forIndexPath: indexPath)
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView
|
||||||
|
{
|
||||||
|
let headerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "Header", forIndexPath: indexPath) as! SaveStatesCollectionHeaderView
|
||||||
|
self.configureCollectionViewHeaderView(headerView, forSection: indexPath.section)
|
||||||
|
return headerView
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - <UICollectionViewDelegate> -
|
//MARK: - <UICollectionViewDelegate> -
|
||||||
@ -289,7 +375,26 @@ extension SaveStatesViewController
|
|||||||
|
|
||||||
switch self.mode
|
switch self.mode
|
||||||
{
|
{
|
||||||
case .Saving: self.updateSaveState(saveState)
|
case .Saving:
|
||||||
|
|
||||||
|
let section = self.correctedSectionForSectionIndex(indexPath.section)
|
||||||
|
switch section
|
||||||
|
{
|
||||||
|
case .Auto: break
|
||||||
|
case .General:
|
||||||
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
|
backgroundContext.performBlockAndWait() {
|
||||||
|
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState
|
||||||
|
self.updateSaveState(temporarySaveState)
|
||||||
|
}
|
||||||
|
|
||||||
|
case .Locked:
|
||||||
|
let alertController = UIAlertController(title: NSLocalizedString("Cannot Modify Locked Save State", comment: ""), message: NSLocalizedString("This save state must first be unlocked before it can be modified.", comment: ""), preferredStyle: .Alert)
|
||||||
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .Cancel, handler: nil))
|
||||||
|
self.presentViewController(alertController, animated: true, completion: nil)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
case .Loading: self.loadSaveState(saveState)
|
case .Loading: self.loadSaveState(saveState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -312,6 +417,14 @@ extension SaveStatesViewController: UICollectionViewDelegateFlowLayout
|
|||||||
let size = self.prototypeCell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
|
let size = self.prototypeCell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize
|
||||||
|
{
|
||||||
|
self.configureCollectionViewHeaderView(self.prototypeHeader, forSection: section)
|
||||||
|
|
||||||
|
let size = self.prototypeHeader.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
|
||||||
|
return size
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - <NSFetchedResultsControllerDelegate> -
|
//MARK: - <NSFetchedResultsControllerDelegate> -
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user