Updated UI for pagination between GameCollections
This commit is contained in:
parent
4a2b5cd1dd
commit
925fb9454d
@ -11,15 +11,13 @@ import CoreData
|
|||||||
|
|
||||||
class GameCollectionViewDataSource: NSObject
|
class GameCollectionViewDataSource: NSObject
|
||||||
{
|
{
|
||||||
var gameTypeIdentifiers: [String] = [] {
|
var supportedGameCollectionIdentifiers: [String]? {
|
||||||
didSet
|
didSet
|
||||||
{
|
{
|
||||||
self.updateFetchedResultsController()
|
self.updateFetchedResultsController()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var sectionTitles: [String] = []
|
|
||||||
|
|
||||||
var cellConfigurationHandler: ((GameCollectionViewCell, Game) -> Void)?
|
var cellConfigurationHandler: ((GameCollectionViewCell, Game) -> Void)?
|
||||||
|
|
||||||
private(set) var fetchedResultsController: NSFetchedResultsController = NSFetchedResultsController()
|
private(set) var fetchedResultsController: NSFetchedResultsController = NSFetchedResultsController()
|
||||||
@ -47,10 +45,13 @@ class GameCollectionViewDataSource: NSObject
|
|||||||
|
|
||||||
var predicates: [NSPredicate] = []
|
var predicates: [NSPredicate] = []
|
||||||
|
|
||||||
for typeIdentifier in self.gameTypeIdentifiers
|
if let identifiers = self.supportedGameCollectionIdentifiers
|
||||||
{
|
{
|
||||||
let predicate = NSPredicate(format: "%K == %@", GameAttributes.typeIdentifier.rawValue, typeIdentifier)
|
for identifier in identifiers
|
||||||
predicates.append(predicate)
|
{
|
||||||
|
let predicate = NSPredicate(format: "SUBQUERY(%K, $x, $x.%K == %@).@count > 0", GameAttributes.gameCollections.rawValue, GameCollectionAttributes.identifier.rawValue, identifier)
|
||||||
|
predicates.append(predicate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if predicates.count > 0
|
if predicates.count > 0
|
||||||
@ -58,7 +59,7 @@ class GameCollectionViewDataSource: NSObject
|
|||||||
fetchRequest.predicate = NSCompoundPredicate(orPredicateWithSubpredicates: predicates)
|
fetchRequest.predicate = NSCompoundPredicate(orPredicateWithSubpredicates: predicates)
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: GameAttributes.name.rawValue, ascending: true)]
|
fetchRequest.sortDescriptors = [NSSortDescriptor(key: GameAttributes.typeIdentifier.rawValue, ascending: true), NSSortDescriptor(key: GameAttributes.name.rawValue, ascending: true)]
|
||||||
|
|
||||||
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: GameAttributes.typeIdentifier.rawValue, cacheName: nil)
|
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: GameAttributes.typeIdentifier.rawValue, cacheName: nil)
|
||||||
self.fetchedResultsController.delegate = previousDelegate
|
self.fetchedResultsController.delegate = previousDelegate
|
||||||
@ -117,6 +118,4 @@ extension GameCollectionViewDataSource: UICollectionViewDelegate
|
|||||||
let size = self.prototypeCell.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
|
let size = self.prototypeCell.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,6 +90,7 @@ class DatabaseManager
|
|||||||
self.validationManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
self.validationManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
||||||
|
|
||||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("managedObjectContextDidSave:"), name: NSManagedObjectContextDidSaveNotification, object: nil)
|
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("managedObjectContextDidSave:"), name: NSManagedObjectContextDidSaveNotification, object: nil)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func startWithCompletion(completionBlock: ((performingMigration: Bool) -> Void)?)
|
func startWithCompletion(completionBlock: ((performingMigration: Bool) -> Void)?)
|
||||||
@ -158,9 +159,9 @@ class DatabaseManager
|
|||||||
game.identifier = identifier
|
game.identifier = identifier
|
||||||
game.filename = filename
|
game.filename = filename
|
||||||
|
|
||||||
if let pathExtension = URL.pathExtension,
|
if let pathExtension = URL.pathExtension
|
||||||
gameCollection = GameCollection.gameSystemCollectionForPathExtension(pathExtension, inManagedObjectContext: managedObjectContext)
|
|
||||||
{
|
{
|
||||||
|
let gameCollection = GameCollection.gameSystemCollectionForPathExtension(pathExtension, inManagedObjectContext: managedObjectContext)
|
||||||
game.typeIdentifier = gameCollection.identifier
|
game.typeIdentifier = gameCollection.identifier
|
||||||
game.gameCollections.insert(gameCollection)
|
game.gameCollections.insert(gameCollection)
|
||||||
}
|
}
|
||||||
@ -171,7 +172,19 @@ class DatabaseManager
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
try NSFileManager.defaultManager().moveItemAtURL(URL, toURL: DatabaseManager.gamesDirectoryURL.URLByAppendingPathComponent(game.identifier + ".smc"))
|
let destinationURL = DatabaseManager.gamesDirectoryURL.URLByAppendingPathComponent(game.identifier + "." + game.preferredFileExtension)
|
||||||
|
|
||||||
|
if let path = destinationURL.path
|
||||||
|
{
|
||||||
|
if NSFileManager.defaultManager().fileExistsAtPath(path)
|
||||||
|
{
|
||||||
|
try NSFileManager.defaultManager().removeItemAtURL(URL)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try NSFileManager.defaultManager().moveItemAtURL(URL, toURL: destinationURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
identifiers.append(game.identifier)
|
identifiers.append(game.identifier)
|
||||||
}
|
}
|
||||||
@ -275,7 +288,36 @@ private extension DatabaseManager
|
|||||||
{
|
{
|
||||||
guard let managedObjectContext = notification.object as? NSManagedObjectContext where managedObjectContext.parentContext == self.validationManagedObjectContext else { return }
|
guard let managedObjectContext = notification.object as? NSManagedObjectContext where managedObjectContext.parentContext == self.validationManagedObjectContext else { return }
|
||||||
|
|
||||||
self.save()
|
self.validationManagedObjectContext.performBlockAndWait {
|
||||||
|
|
||||||
|
// Remove deleted games from disk
|
||||||
|
if let deletedObjects = notification.userInfo?[NSDeletedObjectsKey] as? Set<NSManagedObject>
|
||||||
|
{
|
||||||
|
let games = deletedObjects.filter({ $0 is Game }).map({ self.validationManagedObjectContext.objectWithID($0.objectID) as! Game })
|
||||||
|
|
||||||
|
for game in games
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
try NSFileManager.defaultManager().removeItemAtURL(game.fileURL)
|
||||||
|
}
|
||||||
|
catch let error as NSError
|
||||||
|
{
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove empty collections
|
||||||
|
let collections = GameCollection.instancesWithPredicate(NSPredicate(format: "%K.@count == 0", GameCollectionAttributes.games.rawValue), inManagedObjectContext: self.validationManagedObjectContext, type: GameCollection.self)
|
||||||
|
|
||||||
|
for collection in collections
|
||||||
|
{
|
||||||
|
self.validationManagedObjectContext.deleteObject(collection)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.save()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,8 @@ import CoreData
|
|||||||
import DeltaCore
|
import DeltaCore
|
||||||
import SNESDeltaCore
|
import SNESDeltaCore
|
||||||
|
|
||||||
|
public let kUTTypeGBAGame: CFStringRef = "com.rileytestut.delta.game.gba"
|
||||||
|
|
||||||
@objc(Game)
|
@objc(Game)
|
||||||
class Game: NSManagedObject, GameType
|
class Game: NSManagedObject, GameType
|
||||||
{
|
{
|
||||||
@ -19,12 +21,22 @@ class Game: NSManagedObject, GameType
|
|||||||
let fileURL = DatabaseManager.gamesDirectoryURL.URLByAppendingPathComponent(self.filename)
|
let fileURL = DatabaseManager.gamesDirectoryURL.URLByAppendingPathComponent(self.filename)
|
||||||
return fileURL
|
return fileURL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var preferredFileExtension: String {
|
||||||
|
switch self.typeIdentifier
|
||||||
|
{
|
||||||
|
case kUTTypeSNESGame as String as String: return "smc"
|
||||||
|
case kUTTypeGBAGame as String as String: return "gba"
|
||||||
|
case kUTTypeDeltaGame as String as String: fallthrough
|
||||||
|
default: return "delta"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Game
|
extension Game
|
||||||
{
|
{
|
||||||
class func supportedTypeIdentifiers() -> Set<String>
|
class func supportedTypeIdentifiers() -> Set<String>
|
||||||
{
|
{
|
||||||
return [kUTTypeSNESGame as String]
|
return [kUTTypeSNESGame as String, kUTTypeGBAGame as String]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,18 +14,16 @@ import CoreData
|
|||||||
|
|
||||||
enum GameCollectionAttributes: String
|
enum GameCollectionAttributes: String
|
||||||
{
|
{
|
||||||
case name
|
|
||||||
case identifier
|
case identifier
|
||||||
case shortName
|
case index
|
||||||
|
|
||||||
case games
|
case games
|
||||||
}
|
}
|
||||||
|
|
||||||
extension GameCollection {
|
extension GameCollection {
|
||||||
|
|
||||||
@NSManaged var name: String
|
|
||||||
@NSManaged var identifier: String
|
@NSManaged var identifier: String
|
||||||
@NSManaged var shortName: String?
|
@NSManaged var index: Int16
|
||||||
|
|
||||||
@NSManaged var games: Set<Game>
|
@NSManaged var games: Set<Game>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,31 +9,54 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
import DeltaCore
|
||||||
import SNESDeltaCore
|
import SNESDeltaCore
|
||||||
|
|
||||||
@objc(GameCollection)
|
@objc(GameCollection)
|
||||||
class GameCollection: NSManagedObject
|
class GameCollection: NSManagedObject
|
||||||
{
|
{
|
||||||
class func gameSystemCollectionForPathExtension(pathExtension: String?, inManagedObjectContext managedObjectContext: NSManagedObjectContext) -> GameCollection?
|
var name: String {
|
||||||
|
|
||||||
|
switch self.identifier
|
||||||
|
{
|
||||||
|
case kUTTypeSNESGame as String as String: return NSLocalizedString("Super Nintendo Entertainment System", comment: "")
|
||||||
|
case kUTTypeGBAGame as String as String: return NSLocalizedString("Game Boy Advance", comment: "")
|
||||||
|
case kUTTypeDeltaGame as String as String: return NSLocalizedString("Unsupported Games", comment: "")
|
||||||
|
default: return NSLocalizedString("Unknown", comment: "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var shortName: String {
|
||||||
|
|
||||||
|
switch self.identifier
|
||||||
|
{
|
||||||
|
case kUTTypeSNESGame as String as String: return NSLocalizedString("SNES", comment: "")
|
||||||
|
case kUTTypeGBAGame as String as String: return NSLocalizedString("GBA", comment: "")
|
||||||
|
case kUTTypeDeltaGame as String as String: return NSLocalizedString("Unsupported", comment: "")
|
||||||
|
default: return NSLocalizedString("Unknown", comment: "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class func gameSystemCollectionForPathExtension(pathExtension: String?, inManagedObjectContext managedObjectContext: NSManagedObjectContext) -> GameCollection
|
||||||
{
|
{
|
||||||
guard let pathExtension = pathExtension else { return nil }
|
|
||||||
|
|
||||||
let identifier: String
|
let identifier: String
|
||||||
let name: String
|
let index: Int16
|
||||||
let shortName: String
|
|
||||||
|
|
||||||
switch pathExtension
|
switch pathExtension ?? ""
|
||||||
{
|
{
|
||||||
case "smc": fallthrough
|
case "smc": fallthrough
|
||||||
case "sfc": fallthrough
|
case "sfc": fallthrough
|
||||||
case "fig":
|
case "fig":
|
||||||
identifier = kUTTypeSNESGame as String
|
identifier = kUTTypeSNESGame as String
|
||||||
name = "Super Nintendo Entertainment System"
|
index = 1990
|
||||||
shortName = "SNES"
|
|
||||||
|
|
||||||
|
case "gba":
|
||||||
|
identifier = kUTTypeGBAGame as String
|
||||||
|
index = 2001
|
||||||
|
|
||||||
|
default:
|
||||||
default: return nil
|
identifier = kUTTypeDeltaGame as String
|
||||||
|
index = Int16(INT16_MAX)
|
||||||
}
|
}
|
||||||
|
|
||||||
let predicate = NSPredicate(format: "%K == %@", GameCollectionAttributes.identifier.rawValue, identifier)
|
let predicate = NSPredicate(format: "%K == %@", GameCollectionAttributes.identifier.rawValue, identifier)
|
||||||
@ -43,10 +66,9 @@ class GameCollection: NSManagedObject
|
|||||||
{
|
{
|
||||||
gameCollection = GameCollection.insertIntoManagedObjectContext(managedObjectContext)
|
gameCollection = GameCollection.insertIntoManagedObjectContext(managedObjectContext)
|
||||||
gameCollection?.identifier = identifier
|
gameCollection?.identifier = identifier
|
||||||
gameCollection?.name = name
|
gameCollection?.index = index
|
||||||
gameCollection?.shortName = shortName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return gameCollection
|
return gameCollection!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="9057" systemVersion="15A284" minimumToolsVersion="Xcode 7.0">
|
<model userDefinedModelVersionIdentifier="1.0" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="9057" systemVersion="15B42" minimumToolsVersion="Xcode 7.0">
|
||||||
<entity name="Game" representedClassName="Game" syncable="YES">
|
<entity name="Game" representedClassName="Game" syncable="YES">
|
||||||
<attribute name="artworkURL" optional="YES" attributeType="Transformable" syncable="YES">
|
<attribute name="artworkURL" optional="YES" attributeType="Transformable" syncable="YES">
|
||||||
<userInfo>
|
<userInfo>
|
||||||
@ -23,8 +23,7 @@
|
|||||||
</entity>
|
</entity>
|
||||||
<entity name="GameCollection" representedClassName="GameCollection" syncable="YES">
|
<entity name="GameCollection" representedClassName="GameCollection" syncable="YES">
|
||||||
<attribute name="identifier" attributeType="String" syncable="YES"/>
|
<attribute name="identifier" attributeType="String" syncable="YES"/>
|
||||||
<attribute name="name" attributeType="String" syncable="YES"/>
|
<attribute name="index" attributeType="Integer 16" defaultValueString="0" syncable="YES"/>
|
||||||
<attribute name="shortName" optional="YES" attributeType="String" syncable="YES"/>
|
|
||||||
<relationship name="games" toMany="YES" deletionRule="Nullify" destinationEntity="Game" inverseName="gameCollections" inverseEntity="Game" syncable="YES"/>
|
<relationship name="games" toMany="YES" deletionRule="Nullify" destinationEntity="Game" inverseName="gameCollections" inverseEntity="Game" syncable="YES"/>
|
||||||
<uniquenessConstraints>
|
<uniquenessConstraints>
|
||||||
<uniquenessConstraint>
|
<uniquenessConstraint>
|
||||||
@ -33,7 +32,7 @@
|
|||||||
</uniquenessConstraints>
|
</uniquenessConstraints>
|
||||||
</entity>
|
</entity>
|
||||||
<elements>
|
<elements>
|
||||||
<element name="Game" positionX="-200" positionY="9" width="128" height="133"/>
|
<element name="Game" positionX="-200" positionY="9" width="128" height="135"/>
|
||||||
<element name="GameCollection" positionX="-198" positionY="-207" width="128" height="103"/>
|
<element name="GameCollection" positionX="-198" positionY="-207" width="128" height="90"/>
|
||||||
</elements>
|
</elements>
|
||||||
</model>
|
</model>
|
||||||
@ -9,6 +9,8 @@
|
|||||||
import UIKit
|
import UIKit
|
||||||
import ObjectiveC
|
import ObjectiveC
|
||||||
|
|
||||||
|
import DeltaCore
|
||||||
|
|
||||||
protocol GamePickerControllerDelegate
|
protocol GamePickerControllerDelegate
|
||||||
{
|
{
|
||||||
func gamePickerController(gamePickerController: GamePickerController, didImportGames games: [Game])
|
func gamePickerController(gamePickerController: GamePickerController, didImportGames games: [Game])
|
||||||
@ -59,7 +61,7 @@ class GamePickerController: NSObject
|
|||||||
|
|
||||||
let managedObjectContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let managedObjectContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
managedObjectContext.performBlock() {
|
managedObjectContext.performBlock() {
|
||||||
let gameURLs = contents.filter({ GameCollection.gameSystemCollectionForPathExtension($0.pathExtension, inManagedObjectContext: managedObjectContext) != nil })
|
let gameURLs = contents.filter({ GameCollection.gameSystemCollectionForPathExtension($0.pathExtension, inManagedObjectContext: managedObjectContext).identifier != kUTTypeDeltaGame as String })
|
||||||
self.importGamesAtURLs(gameURLs)
|
self.importGamesAtURLs(gameURLs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
AF0535CD7331785FA15E0864 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22506DA00971C4300AF90A35 /* Pods.framework */; };
|
AF0535CD7331785FA15E0864 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22506DA00971C4300AF90A35 /* Pods.framework */; };
|
||||||
BF090CF41B490D8300DCAB45 /* UIDevice+Vibration.m in Sources */ = {isa = PBXBuildFile; fileRef = BF090CF31B490D8300DCAB45 /* UIDevice+Vibration.m */; };
|
BF090CF41B490D8300DCAB45 /* UIDevice+Vibration.m in Sources */ = {isa = PBXBuildFile; fileRef = BF090CF31B490D8300DCAB45 /* UIDevice+Vibration.m */; };
|
||||||
|
BF107EC41BF413F000E0C32C /* GamesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF107EC31BF413F000E0C32C /* GamesViewController.swift */; };
|
||||||
BF27CC8B1BC9FE4D00A20D89 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF27CC8A1BC9FE4D00A20D89 /* Pods.framework */; };
|
BF27CC8B1BC9FE4D00A20D89 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF27CC8A1BC9FE4D00A20D89 /* Pods.framework */; };
|
||||||
BF27CC8C1BC9FE5300A20D89 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22506DA00971C4300AF90A35 /* Pods.framework */; };
|
BF27CC8C1BC9FE5300A20D89 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22506DA00971C4300AF90A35 /* Pods.framework */; };
|
||||||
BF27CC8D1BC9FE5300A20D89 /* Pods.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 22506DA00971C4300AF90A35 /* Pods.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
BF27CC8D1BC9FE5300A20D89 /* Pods.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 22506DA00971C4300AF90A35 /* Pods.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
@ -17,7 +18,6 @@
|
|||||||
BF27CC911BCB156200A20D89 /* EmulationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF27CC901BCB156200A20D89 /* EmulationViewController.swift */; };
|
BF27CC911BCB156200A20D89 /* EmulationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF27CC901BCB156200A20D89 /* EmulationViewController.swift */; };
|
||||||
BF27CC951BCB7B7A00A20D89 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF27CC941BCB7B7A00A20D89 /* GameController.framework */; };
|
BF27CC951BCB7B7A00A20D89 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF27CC941BCB7B7A00A20D89 /* GameController.framework */; };
|
||||||
BF27CC971BCC890700A20D89 /* GamesCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF27CC961BCC890700A20D89 /* GamesCollectionViewController.swift */; };
|
BF27CC971BCC890700A20D89 /* GamesCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF27CC961BCC890700A20D89 /* GamesCollectionViewController.swift */; };
|
||||||
BF27CC991BCC8AE600A20D89 /* GamesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF27CC981BCC8AE600A20D89 /* GamesViewController.swift */; };
|
|
||||||
BF2A53FB1BB74FC10052BD0C /* SNESDeltaCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFC134E01AAD82460087AD7B /* SNESDeltaCore.framework */; };
|
BF2A53FB1BB74FC10052BD0C /* SNESDeltaCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFC134E01AAD82460087AD7B /* SNESDeltaCore.framework */; };
|
||||||
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 */; };
|
||||||
@ -112,12 +112,12 @@
|
|||||||
BF090CF11B490D8300DCAB45 /* Delta-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Delta-Bridging-Header.h"; sourceTree = "<group>"; };
|
BF090CF11B490D8300DCAB45 /* Delta-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Delta-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
BF090CF21B490D8300DCAB45 /* UIDevice+Vibration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIDevice+Vibration.h"; sourceTree = "<group>"; };
|
BF090CF21B490D8300DCAB45 /* UIDevice+Vibration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIDevice+Vibration.h"; sourceTree = "<group>"; };
|
||||||
BF090CF31B490D8300DCAB45 /* UIDevice+Vibration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIDevice+Vibration.m"; sourceTree = "<group>"; };
|
BF090CF31B490D8300DCAB45 /* UIDevice+Vibration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIDevice+Vibration.m"; sourceTree = "<group>"; };
|
||||||
|
BF107EC31BF413F000E0C32C /* GamesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GamesViewController.swift; sourceTree = "<group>"; };
|
||||||
BF27CC861BC9E3C600A20D89 /* Delta.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Delta.entitlements; sourceTree = "<group>"; };
|
BF27CC861BC9E3C600A20D89 /* Delta.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Delta.entitlements; sourceTree = "<group>"; };
|
||||||
BF27CC8A1BC9FE4D00A20D89 /* Pods.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Pods.framework; path = "Pods/../build/Debug-appletvos/Pods.framework"; sourceTree = "<group>"; };
|
BF27CC8A1BC9FE4D00A20D89 /* Pods.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Pods.framework; path = "Pods/../build/Debug-appletvos/Pods.framework"; sourceTree = "<group>"; };
|
||||||
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>"; };
|
||||||
BF27CC981BCC8AE600A20D89 /* GamesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GamesViewController.swift; sourceTree = "<group>"; };
|
|
||||||
BF4566E71BC090B6007BFA1A /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = "<group>"; };
|
BF4566E71BC090B6007BFA1A /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = "<group>"; };
|
||||||
BF50DC411BD851740024C720 /* GameCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GameCollectionViewCell.swift; path = "Collection View/GameCollectionViewCell.swift"; sourceTree = "<group>"; };
|
BF50DC411BD851740024C720 /* GameCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GameCollectionViewCell.swift; path = "Collection View/GameCollectionViewCell.swift"; sourceTree = "<group>"; };
|
||||||
BF5E7F431B9A650B00AE44F8 /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
|
BF5E7F431B9A650B00AE44F8 /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
|
||||||
@ -204,7 +204,6 @@
|
|||||||
BF4566E31BC09026007BFA1A /* Common */ = {
|
BF4566E31BC09026007BFA1A /* Common */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
BFC273151BE612CE00D22B05 /* Model */,
|
|
||||||
BFF1E55F1BE04BF6000E9EF6 /* Components */,
|
BFF1E55F1BE04BF6000E9EF6 /* Components */,
|
||||||
BF9257571BD8244800B109DA /* Collection View */,
|
BF9257571BD8244800B109DA /* Collection View */,
|
||||||
BF4566E41BC0902E007BFA1A /* Database */,
|
BF4566E41BC0902E007BFA1A /* Database */,
|
||||||
@ -238,7 +237,7 @@
|
|||||||
BF46894D1AAC469800A2586D /* Game Selection */ = {
|
BF46894D1AAC469800A2586D /* Game Selection */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
BF27CC981BCC8AE600A20D89 /* GamesViewController.swift */,
|
BF107EC31BF413F000E0C32C /* GamesViewController.swift */,
|
||||||
BF27CC961BCC890700A20D89 /* GamesCollectionViewController.swift */,
|
BF27CC961BCC890700A20D89 /* GamesCollectionViewController.swift */,
|
||||||
);
|
);
|
||||||
path = "Game Selection";
|
path = "Game Selection";
|
||||||
@ -308,13 +307,6 @@
|
|||||||
path = Settings;
|
path = Settings;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
BFC273151BE612CE00D22B05 /* Model */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
);
|
|
||||||
name = Model;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
BFDB28431BC9D9D1001D0C83 /* Importing */ = {
|
BFDB28431BC9D9D1001D0C83 /* Importing */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -632,7 +624,6 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
BF27CC991BCC8AE600A20D89 /* GamesViewController.swift in Sources */,
|
|
||||||
BFF4EA011BE1B2420056AAA4 /* GameCollectionViewLayoutAttributes.swift in Sources */,
|
BFF4EA011BE1B2420056AAA4 /* GameCollectionViewLayoutAttributes.swift in Sources */,
|
||||||
BFAA1FED1B8AA4FA00495943 /* Settings.swift in Sources */,
|
BFAA1FED1B8AA4FA00495943 /* Settings.swift in Sources */,
|
||||||
BF50DC421BD851740024C720 /* GameCollectionViewCell.swift in Sources */,
|
BF50DC421BD851740024C720 /* GameCollectionViewCell.swift in Sources */,
|
||||||
@ -650,6 +641,7 @@
|
|||||||
BFA5342A1BDC6B520088F1BE /* GameCollectionViewLayout.swift in Sources */,
|
BFA5342A1BDC6B520088F1BE /* GameCollectionViewLayout.swift in Sources */,
|
||||||
BF762E9E1BC19D31002C8866 /* DatabaseManager.swift in Sources */,
|
BF762E9E1BC19D31002C8866 /* DatabaseManager.swift in Sources */,
|
||||||
BF090CF41B490D8300DCAB45 /* UIDevice+Vibration.m in Sources */,
|
BF090CF41B490D8300DCAB45 /* UIDevice+Vibration.m in Sources */,
|
||||||
|
BF107EC41BF413F000E0C32C /* GamesViewController.swift in Sources */,
|
||||||
BF5E7F441B9A650B00AE44F8 /* SettingsViewController.swift in Sources */,
|
BF5E7F441B9A650B00AE44F8 /* SettingsViewController.swift in Sources */,
|
||||||
BFDB28451BC9DA7B001D0C83 /* GamePickerController.swift in Sources */,
|
BFDB28451BC9DA7B001D0C83 /* GamePickerController.swift in Sources */,
|
||||||
BFDE393A1BC0CEDF003F72E8 /* Game+CoreDataProperties.swift in Sources */,
|
BFDE393A1BC0CEDF003F72E8 /* Game+CoreDataProperties.swift in Sources */,
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "A1BF268530E217C860B34A81A1DA1B446006BF9E",
|
||||||
"DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
|
"DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
|
||||||
|
|
||||||
},
|
},
|
||||||
@ -6,6 +7,7 @@
|
|||||||
"377491A212AA92C1503AD101C88ADDBD6FD62CF0" : 0,
|
"377491A212AA92C1503AD101C88ADDBD6FD62CF0" : 0,
|
||||||
"C14902E1A817B9BD0549E16C5F6A56E2377FBF42" : 0,
|
"C14902E1A817B9BD0549E16C5F6A56E2377FBF42" : 0,
|
||||||
"816D57F18EE93972A535858CB18F29A85BE91A39" : 0,
|
"816D57F18EE93972A535858CB18F29A85BE91A39" : 0,
|
||||||
|
"A1BF268530E217C860B34A81A1DA1B446006BF9E" : 0,
|
||||||
"82DF43EF5CA016D15C41E0AF1AF686E9973475B7" : 0
|
"82DF43EF5CA016D15C41E0AF1AF686E9973475B7" : 0
|
||||||
},
|
},
|
||||||
"DVTSourceControlWorkspaceBlueprintIdentifierKey" : "8EE86D07-2AAF-47C3-91DF-0E46DBDAB128",
|
"DVTSourceControlWorkspaceBlueprintIdentifierKey" : "8EE86D07-2AAF-47C3-91DF-0E46DBDAB128",
|
||||||
@ -13,6 +15,7 @@
|
|||||||
"377491A212AA92C1503AD101C88ADDBD6FD62CF0" : "Delta\/External\/Roxas\/",
|
"377491A212AA92C1503AD101C88ADDBD6FD62CF0" : "Delta\/External\/Roxas\/",
|
||||||
"C14902E1A817B9BD0549E16C5F6A56E2377FBF42" : "Delta\/Cores\/SNESDeltaCore\/",
|
"C14902E1A817B9BD0549E16C5F6A56E2377FBF42" : "Delta\/Cores\/SNESDeltaCore\/",
|
||||||
"816D57F18EE93972A535858CB18F29A85BE91A39" : "Delta\/Cores\/DeltaCore\/",
|
"816D57F18EE93972A535858CB18F29A85BE91A39" : "Delta\/Cores\/DeltaCore\/",
|
||||||
|
"A1BF268530E217C860B34A81A1DA1B446006BF9E" : "Delta\/",
|
||||||
"82DF43EF5CA016D15C41E0AF1AF686E9973475B7" : "Delta\/Cores\/DeltaCore\/External\/ZipZap\/"
|
"82DF43EF5CA016D15C41E0AF1AF686E9973475B7" : "Delta\/Cores\/DeltaCore\/External\/ZipZap\/"
|
||||||
},
|
},
|
||||||
"DVTSourceControlWorkspaceBlueprintNameKey" : "Delta",
|
"DVTSourceControlWorkspaceBlueprintNameKey" : "Delta",
|
||||||
@ -34,6 +37,11 @@
|
|||||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "82DF43EF5CA016D15C41E0AF1AF686E9973475B7"
|
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "82DF43EF5CA016D15C41E0AF1AF686E9973475B7"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:rileytestut\/Delta.git",
|
||||||
|
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||||
|
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "A1BF268530E217C860B34A81A1DA1B446006BF9E"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:rileytestut\/SNESDeltaCore.git",
|
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:rileytestut\/SNESDeltaCore.git",
|
||||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9059" systemVersion="15A284" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="wKV-3d-NIY">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9059" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="wKV-3d-NIY">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@ -79,7 +79,7 @@
|
|||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tmn-gd-5UN">
|
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tmn-gd-5UN">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
<rect key="frame" x="0.0" y="0.0" width="600" height="556"/>
|
||||||
<animations/>
|
<animations/>
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="tpK-ou-yEA" kind="embed" id="cjU-nW-cHY"/>
|
<segue destination="tpK-ou-yEA" kind="embed" id="cjU-nW-cHY"/>
|
||||||
@ -239,12 +239,18 @@
|
|||||||
<objects>
|
<objects>
|
||||||
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="wKV-3d-NIY" sceneMemberID="viewController">
|
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="wKV-3d-NIY" sceneMemberID="viewController">
|
||||||
<toolbarItems/>
|
<toolbarItems/>
|
||||||
|
<nil key="simulatedBottomBarMetrics"/>
|
||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="wj9-1e-eev">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" id="wj9-1e-eev">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<animations/>
|
<animations/>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
<nil name="viewControllers"/>
|
<nil name="viewControllers"/>
|
||||||
|
<toolbar key="toolbar" opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="M4r-sO-G4H">
|
||||||
|
<rect key="frame" x="0.0" y="556" width="600" height="44"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<animations/>
|
||||||
|
</toolbar>
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="jeE-WD-wXO" kind="relationship" relationship="rootViewController" id="JbW-Xm-9mu"/>
|
<segue destination="jeE-WD-wXO" kind="relationship" relationship="rootViewController" id="JbW-Xm-9mu"/>
|
||||||
</connections>
|
</connections>
|
||||||
|
|||||||
@ -13,10 +13,11 @@ import DeltaCore
|
|||||||
|
|
||||||
class GamesCollectionViewController: UICollectionViewController
|
class GamesCollectionViewController: UICollectionViewController
|
||||||
{
|
{
|
||||||
var gameTypeIdentifier: String! {
|
var gameCollection: GameCollection! {
|
||||||
didSet
|
didSet
|
||||||
{
|
{
|
||||||
self.dataSource.gameTypeIdentifiers = [self.gameTypeIdentifier]
|
self.dataSource.supportedGameCollectionIdentifiers = [self.gameCollection.identifier]
|
||||||
|
self.title = self.gameCollection.shortName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,14 +7,35 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import CoreData
|
||||||
|
|
||||||
import SNESDeltaCore
|
import SNESDeltaCore
|
||||||
|
|
||||||
|
import Roxas
|
||||||
|
|
||||||
class GamesViewController: UIViewController
|
class GamesViewController: UIViewController
|
||||||
{
|
{
|
||||||
var pageViewController: UIPageViewController! = nil
|
private var pageViewController: UIPageViewController!
|
||||||
|
private var backgroundView: RSTBackgroundView!
|
||||||
|
private var pageControl: UIPageControl!
|
||||||
|
|
||||||
let supportedGameTypeIdentifiers = [kUTTypeSNESGame as String]
|
private let fetchedResultsController: NSFetchedResultsController
|
||||||
|
|
||||||
|
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
|
||||||
|
fatalError("initWithNibName: not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder)
|
||||||
|
{
|
||||||
|
let fetchRequest = GameCollection.fetchRequest()
|
||||||
|
fetchRequest.sortDescriptors = [NSSortDescriptor(key: GameCollectionAttributes.index.rawValue, ascending: true)]
|
||||||
|
|
||||||
|
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
|
||||||
|
|
||||||
|
super.init(coder: aDecoder)
|
||||||
|
|
||||||
|
self.fetchedResultsController.delegate = self
|
||||||
|
}
|
||||||
|
|
||||||
override func viewDidLoad()
|
override func viewDidLoad()
|
||||||
{
|
{
|
||||||
@ -22,22 +43,59 @@ class GamesViewController: UIViewController
|
|||||||
|
|
||||||
self.automaticallyAdjustsScrollViewInsets = false
|
self.automaticallyAdjustsScrollViewInsets = false
|
||||||
|
|
||||||
|
self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
|
||||||
|
self.backgroundView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
|
||||||
|
self.backgroundView.textLabel.text = NSLocalizedString("No Games", comment: "")
|
||||||
|
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can import games by pressing the + button in the top right.", comment: "")
|
||||||
|
self.view.insertSubview(self.backgroundView, atIndex: 0)
|
||||||
|
|
||||||
self.pageViewController = self.childViewControllers.first as? UIPageViewController
|
self.pageViewController = self.childViewControllers.first as? UIPageViewController
|
||||||
self.pageViewController.dataSource = self
|
self.pageViewController.dataSource = self
|
||||||
self.pageViewController.delegate = self
|
self.pageViewController.delegate = self
|
||||||
|
self.pageViewController.view.hidden = true
|
||||||
|
|
||||||
let viewController = self.viewControllerForIndex(0)
|
self.pageControl = UIPageControl()
|
||||||
self.pageViewController.setViewControllers([viewController], direction: .Forward, animated: false, completion: nil)
|
self.pageControl.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
self.pageControl.hidesForSinglePage = false
|
||||||
|
self.pageControl.numberOfPages = 3
|
||||||
|
self.pageControl.currentPageIndicatorTintColor = UIColor.purpleColor()
|
||||||
|
self.pageControl.pageIndicatorTintColor = UIColor.lightGrayColor()
|
||||||
|
self.navigationController?.toolbar.addSubview(self.pageControl)
|
||||||
|
|
||||||
// Do any additional setup after loading the view.
|
self.pageControl.centerXAnchor.constraintEqualToAnchor(self.navigationController?.toolbar.centerXAnchor, constant: 0).active = true
|
||||||
|
self.pageControl.centerYAnchor.constraintEqualToAnchor(self.navigationController?.toolbar.centerYAnchor, constant: 0).active = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewWillAppear(animated: Bool)
|
||||||
|
{
|
||||||
|
super.viewWillAppear(animated)
|
||||||
|
|
||||||
|
if self.fetchedResultsController.fetchedObjects == nil
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
try self.fetchedResultsController.performFetch()
|
||||||
|
}
|
||||||
|
catch let error as NSError
|
||||||
|
{
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.updateSections()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidLayoutSubviews()
|
override func viewDidLayoutSubviews()
|
||||||
{
|
{
|
||||||
super.viewDidLayoutSubviews()
|
super.viewDidLayoutSubviews()
|
||||||
|
|
||||||
let viewController = self.pageViewController.viewControllers?.first as! GamesCollectionViewController
|
if let viewControllers = self.pageViewController.viewControllers as? [GamesCollectionViewController]
|
||||||
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
|
{
|
||||||
|
for viewController in viewControllers
|
||||||
|
{
|
||||||
|
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func didReceiveMemoryWarning() {
|
override func didReceiveMemoryWarning() {
|
||||||
@ -57,20 +115,83 @@ class GamesViewController: UIViewController
|
|||||||
|
|
||||||
private extension GamesViewController
|
private extension GamesViewController
|
||||||
{
|
{
|
||||||
func viewControllerForIndex(index: Int) -> GamesCollectionViewController
|
func viewControllerForIndex(index: Int) -> GamesCollectionViewController?
|
||||||
{
|
{
|
||||||
var safeIndex = index % self.supportedGameTypeIdentifiers.count
|
guard let pages = self.fetchedResultsController.sections?.first?.numberOfObjects where pages > 0 else { return nil }
|
||||||
|
|
||||||
|
// Return nil if only one section, and not asking for the 0th view controller
|
||||||
|
guard !(pages == 1 && index != 0) else { return nil }
|
||||||
|
|
||||||
|
var safeIndex = index % pages
|
||||||
if safeIndex < 0
|
if safeIndex < 0
|
||||||
{
|
{
|
||||||
safeIndex = self.supportedGameTypeIdentifiers.count + safeIndex
|
safeIndex = pages + safeIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let indexPath = NSIndexPath(forRow: safeIndex, inSection: 0)
|
||||||
|
|
||||||
let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("gamesCollectionViewController") as! GamesCollectionViewController
|
let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("gamesCollectionViewController") as! GamesCollectionViewController
|
||||||
viewController.gameTypeIdentifier = self.supportedGameTypeIdentifiers[safeIndex] as String
|
viewController.gameCollection = self.fetchedResultsController.objectAtIndexPath(indexPath) as! GameCollection
|
||||||
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
|
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
|
||||||
|
|
||||||
return viewController
|
return viewController
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateSections()
|
||||||
|
{
|
||||||
|
let sections = self.fetchedResultsController.sections?.first?.numberOfObjects ?? 0
|
||||||
|
self.pageControl.numberOfPages = sections
|
||||||
|
|
||||||
|
var resetPageViewController = false
|
||||||
|
|
||||||
|
if let viewController = pageViewController.viewControllers?.first as? GamesCollectionViewController, let gameCollection = viewController.gameCollection
|
||||||
|
{
|
||||||
|
if let index = self.fetchedResultsController.fetchedObjects?.indexOf({ $0 as! GameCollection == gameCollection })
|
||||||
|
{
|
||||||
|
self.pageControl.currentPage = index
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resetPageViewController = true
|
||||||
|
|
||||||
|
self.pageControl.currentPage = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
self.navigationController?.setToolbarHidden(sections < 2, animated: self.view.window != nil)
|
||||||
|
|
||||||
|
if sections > 0
|
||||||
|
{
|
||||||
|
// Reset page view controller if currently hidden or current child should view controller no longer exists
|
||||||
|
if self.pageViewController.view.hidden || resetPageViewController
|
||||||
|
{
|
||||||
|
if let viewController = self.viewControllerForIndex(0)
|
||||||
|
{
|
||||||
|
self.pageViewController.view.hidden = false
|
||||||
|
self.backgroundView.hidden = true
|
||||||
|
|
||||||
|
self.pageViewController.setViewControllers([viewController], direction: .Forward, animated: false, completion: nil)
|
||||||
|
|
||||||
|
self.title = viewController.title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.pageViewController.setViewControllers(self.pageViewController.viewControllers, direction: .Forward, animated: false, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.title = NSLocalizedString("Games", comment: "")
|
||||||
|
|
||||||
|
if !self.pageViewController.view.hidden
|
||||||
|
{
|
||||||
|
self.pageViewController.view.hidden = true
|
||||||
|
self.backgroundView.hidden = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension GamesViewController: GamePickerControllerDelegate
|
extension GamesViewController: GamePickerControllerDelegate
|
||||||
@ -85,15 +206,32 @@ extension GamesViewController: UIPageViewControllerDelegate, UIPageViewControlle
|
|||||||
{
|
{
|
||||||
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
|
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
|
||||||
{
|
{
|
||||||
let index = self.supportedGameTypeIdentifiers.indexOf((viewController as! GamesCollectionViewController).gameTypeIdentifier)
|
let viewController = self.viewControllerForIndex(self.pageControl.currentPage - 1)
|
||||||
let viewController = self.viewControllerForIndex(index! - 1)
|
|
||||||
return viewController
|
return viewController
|
||||||
}
|
}
|
||||||
|
|
||||||
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController?
|
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController?
|
||||||
{
|
{
|
||||||
let index = self.supportedGameTypeIdentifiers.indexOf((viewController as! GamesCollectionViewController).gameTypeIdentifier)
|
let viewController = self.viewControllerForIndex(self.pageControl.currentPage + 1)
|
||||||
let viewController = self.viewControllerForIndex(index! + 1)
|
|
||||||
return viewController
|
return viewController
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool)
|
||||||
|
{
|
||||||
|
if let viewController = pageViewController.viewControllers?.first as? GamesCollectionViewController, let gameCollection = viewController.gameCollection
|
||||||
|
{
|
||||||
|
let index = self.fetchedResultsController.fetchedObjects?.indexOf({ $0 as! GameCollection == gameCollection }) ?? 0
|
||||||
|
self.pageControl.currentPage = index
|
||||||
|
}
|
||||||
|
|
||||||
|
self.title = pageViewController.viewControllers?.first?.title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension GamesViewController: NSFetchedResultsControllerDelegate
|
||||||
|
{
|
||||||
|
func controllerDidChangeContent(controller: NSFetchedResultsController)
|
||||||
|
{
|
||||||
|
self.updateSections()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,9 +11,12 @@ import CoreData
|
|||||||
|
|
||||||
import SNESDeltaCore
|
import SNESDeltaCore
|
||||||
|
|
||||||
|
import Roxas
|
||||||
|
|
||||||
class GameSelectionViewController: UICollectionViewController
|
class GameSelectionViewController: UICollectionViewController
|
||||||
{
|
{
|
||||||
private let dataSource = GameCollectionViewDataSource()
|
private let dataSource = GameCollectionViewDataSource()
|
||||||
|
private var backgroundView: RSTBackgroundView! = nil
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder)
|
required init?(coder aDecoder: NSCoder)
|
||||||
{
|
{
|
||||||
@ -21,7 +24,7 @@ class GameSelectionViewController: UICollectionViewController
|
|||||||
|
|
||||||
self.title = NSLocalizedString("Games", comment: "")
|
self.title = NSLocalizedString("Games", comment: "")
|
||||||
|
|
||||||
self.dataSource.gameTypeIdentifiers = [kUTTypeSNESGame as String]
|
self.dataSource.supportedGameCollectionIdentifiers = [kUTTypeSNESGame as String, kUTTypeGBAGame as String]
|
||||||
self.dataSource.fetchedResultsController.delegate = self
|
self.dataSource.fetchedResultsController.delegate = self
|
||||||
self.dataSource.cellConfigurationHandler = self.configureCell
|
self.dataSource.cellConfigurationHandler = self.configureCell
|
||||||
}
|
}
|
||||||
@ -37,11 +40,18 @@ class GameSelectionViewController: UICollectionViewController
|
|||||||
{
|
{
|
||||||
layout.maximumBoxArtSize = CGSize(width: 200, height: 200)
|
layout.maximumBoxArtSize = CGSize(width: 200, height: 200)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
|
||||||
|
self.backgroundView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
|
||||||
|
self.backgroundView.textLabel.text = NSLocalizedString("No Games", comment: "")
|
||||||
|
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can import games by pressing the + button in the top right.", comment: "")
|
||||||
|
self.view.addSubview(self.backgroundView)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(animated: Bool)
|
override func viewWillAppear(animated: Bool)
|
||||||
{
|
{
|
||||||
self.dataSource.update()
|
self.dataSource.update()
|
||||||
|
self.updateCollections()
|
||||||
|
|
||||||
super.viewWillAppear(animated)
|
super.viewWillAppear(animated)
|
||||||
}
|
}
|
||||||
@ -83,6 +93,23 @@ class GameSelectionViewController: UICollectionViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extension GameSelectionViewController
|
||||||
|
{
|
||||||
|
func updateCollections()
|
||||||
|
{
|
||||||
|
if self.dataSource.fetchedResultsController.sections?.count ?? 0 == 0
|
||||||
|
{
|
||||||
|
self.backgroundView.hidden = false
|
||||||
|
self.collectionView?.hidden = true
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.backgroundView.hidden = true
|
||||||
|
self.collectionView?.hidden = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - <GamePickerControllerDelegate> -
|
// MARK: - <GamePickerControllerDelegate> -
|
||||||
extension GameSelectionViewController: GamePickerControllerDelegate
|
extension GameSelectionViewController: GamePickerControllerDelegate
|
||||||
{
|
{
|
||||||
@ -97,6 +124,8 @@ extension GameSelectionViewController: NSFetchedResultsControllerDelegate
|
|||||||
func controllerDidChangeContent(controller: NSFetchedResultsController)
|
func controllerDidChangeContent(controller: NSFetchedResultsController)
|
||||||
{
|
{
|
||||||
self.collectionView?.reloadData()
|
self.collectionView?.reloadData()
|
||||||
|
|
||||||
|
self.updateCollections()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
External/Roxas
vendored
2
External/Roxas
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 9789612ecbdfd17a8c94b52f4872ec70d44cc4aa
|
Subproject commit 12973b60eeddd6e5b3b398d5ec5b2dadd461810d
|
||||||
Loading…
Reference in New Issue
Block a user