Refactors GamesViewController & GameCollectionViewController (previously GamesCollectionViewController)

This commit is contained in:
Riley Testut 2016-08-12 15:23:37 -05:00
parent 9e66df0ace
commit 21c5d13ba2
9 changed files with 218 additions and 301 deletions

View File

@ -1,126 +0,0 @@
//
// GameCollectionViewDataSource.swift
// Delta
//
// Created by Riley Testut on 10/30/15.
// Copyright © 2015 Riley Testut. All rights reserved.
//
import UIKit
import CoreData
class GameCollectionViewDataSource: NSObject
{
var supportedGameCollectionIdentifiers: [String]? {
didSet
{
self.updateFetchedResultsController()
}
}
var cellConfigurationHandler: ((GridCollectionViewCell, Game) -> Void)?
private(set) var fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult> = NSFetchedResultsController<NSFetchRequestResult>()
private var prototypeCell = GridCollectionViewCell()
private var _registeredCollectionViewCells = false
// MARK: - Update -
func update()
{
do
{
try self.fetchedResultsController.performFetch()
}
catch let error as NSError
{
print(error)
}
}
private func updateFetchedResultsController()
{
let previousDelegate = self.fetchedResultsController.delegate
let fetchRequest = Game.rst_fetchRequest()
var predicates: [NSPredicate] = []
if let identifiers = self.supportedGameCollectionIdentifiers
{
for identifier in identifiers
{
let predicate = NSPredicate(format: "SUBQUERY(%K, $x, $x.%K == %@).@count > 0", Game.Attributes.gameCollections.rawValue, GameCollection.Attributes.identifier.rawValue, identifier)
predicates.append(predicate)
}
}
if predicates.count > 0
{
fetchRequest.predicate = NSCompoundPredicate(orPredicateWithSubpredicates: predicates)
}
fetchRequest.sortDescriptors = [NSSortDescriptor(key: Game.Attributes.type.rawValue, ascending: true), NSSortDescriptor(key: Game.Attributes.name.rawValue, ascending: true)]
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.shared.viewContext, sectionNameKeyPath: Game.Attributes.type.rawValue, cacheName: nil)
self.fetchedResultsController.delegate = previousDelegate
self.update()
}
// MARK: - Collection View -
private func configureCell(_ cell: GridCollectionViewCell, forIndexPath indexPath: IndexPath)
{
let game = self.fetchedResultsController.object(at: indexPath) as! Game
if let handler = self.cellConfigurationHandler
{
handler(cell, game)
}
}
}
extension GameCollectionViewDataSource: UICollectionViewDataSource
{
func numberOfSections(in collectionView: UICollectionView) -> Int
{
return self.fetchedResultsController.sections?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
let count = self.fetchedResultsController.sections?[section].numberOfObjects ?? 0
return count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "GameCell", for: indexPath) as! GridCollectionViewCell
self.configureCell(cell, forIndexPath: indexPath)
return cell
}
}
extension GameCollectionViewDataSource: UICollectionViewDelegate
{
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize
{
let collectionViewLayout = collectionView.collectionViewLayout as! GridCollectionViewLayout
let widthConstraint = self.prototypeCell.contentView.widthAnchor.constraint(equalToConstant: collectionViewLayout.itemWidth)
widthConstraint.isActive = true
self.configureCell(self.prototypeCell, forIndexPath: indexPath)
let size = self.prototypeCell.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
widthConstraint.isActive = false
return size
}
}

View File

@ -10,6 +10,6 @@
@interface NSFetchedResultsController (Conveniences)
- (void)performFetchIfNeeded;
- (BOOL)performFetchIfNeeded;
@end

View File

@ -12,20 +12,21 @@
@implementation NSFetchedResultsController (Conveniences)
// Needs to be implemented in Objective-C due to current limitation of Swift:
// Extension of a generic Objective-C class cannot access the class's generic parameters at runtime
- (void)performFetchIfNeeded
// Needs to be implemented in Objective-C, because it crashes the Swift compiler :(
- (BOOL)performFetchIfNeeded
{
if (self.fetchedObjects != nil)
if (self.sections != nil)
{
return;
return NO;
}
NSError *error = nil;
if (![self performFetch:&error])
{
ELog(error);
}
return YES;
}
@end

View File

@ -7,7 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
BF02BD001D361BD1000892F2 /* NSFetchedResultsController+Conveniences.m in Sources */ = {isa = PBXBuildFile; fileRef = BF02BCFF1D361BD1000892F2 /* NSFetchedResultsController+Conveniences.m */; };
BF0418141D01E93400E85BCF /* GBADeltaCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF0418131D01E93400E85BCF /* GBADeltaCore.framework */; };
BF0418151D01E93400E85BCF /* GBADeltaCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BF0418131D01E93400E85BCF /* GBADeltaCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
BF090CF41B490D8300DCAB45 /* UIDevice+Vibration.m in Sources */ = {isa = PBXBuildFile; fileRef = BF090CF31B490D8300DCAB45 /* UIDevice+Vibration.m */; };
@ -18,7 +17,6 @@
BF172AEB1C68986300C26774 /* NSManagedObjectContext+Conveniences.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF172AEA1C68986300C26774 /* NSManagedObjectContext+Conveniences.swift */; };
BF1FB1861C5EE643007E2494 /* SaveState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1FB1831C5EE643007E2494 /* SaveState.swift */; };
BF27CC8E1BC9FEA200A20D89 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BF6BB2451BB73FE800CCF94A /* Assets.xcassets */; };
BF27CC971BCC890700A20D89 /* GamesCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF27CC961BCC890700A20D89 /* GamesCollectionViewController.swift */; };
BF2B98E61C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF2B98E51C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift */; };
BF31878B1D489AAA00BD020D /* CheatValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF31878A1D489AAA00BD020D /* CheatValidator.swift */; };
BF34FA071CF0F510006624C7 /* EditCheatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF34FA061CF0F510006624C7 /* EditCheatViewController.swift */; };
@ -50,13 +48,14 @@
BFA2315C1CED10BE0011E35A /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA2315B1CED10BE0011E35A /* Action.swift */; };
BFAA1FED1B8AA4FA00495943 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFAA1FEC1B8AA4FA00495943 /* Settings.swift */; };
BFAA1FF41B8AD7F900495943 /* ControllersSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFAA1FF31B8AD7F900495943 /* ControllersSettingsViewController.swift */; };
BFB141181BE46934004FBF46 /* GameCollectionViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFB141171BE46934004FBF46 /* GameCollectionViewDataSource.swift */; };
BFBAA86A1D5A483900A29C1B /* DatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBAA8691D5A483900A29C1B /* DatabaseManager.swift */; };
BFC2731A1BE6152200D22B05 /* GameCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC273171BE6152200D22B05 /* GameCollection.swift */; };
BFC9B7391CEFCD34008629BB /* CheatsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC9B7381CEFCD34008629BB /* CheatsViewController.swift */; };
BFCEA67E1D56FF640061A534 /* UIViewControllerContextTransitioning+Conveniences.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFCEA67D1D56FF640061A534 /* UIViewControllerContextTransitioning+Conveniences.swift */; };
BFD097211D3A01B8005A44C2 /* SaveStatesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3540041C5DA70400C1184C /* SaveStatesViewController.swift */; };
BFDB28451BC9DA7B001D0C83 /* GamePickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDB28441BC9DA7B001D0C83 /* GamePickerController.swift */; };
BFDD04EF1D5E27DB002D450E /* NSFetchedResultsController+Conveniences.m in Sources */ = {isa = PBXBuildFile; fileRef = BF02BCFF1D361BD1000892F2 /* NSFetchedResultsController+Conveniences.m */; };
BFDD04F11D5E2C27002D450E /* GameCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDD04F01D5E2C27002D450E /* GameCollectionViewController.swift */; };
BFDE393C1BC0CEDF003F72E8 /* Game.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDE39391BC0CEDF003F72E8 /* Game.swift */; };
BFE704F51CEA426E0058BAC8 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22506DA00971C4300AF90A35 /* Pods.framework */; };
BFEC732D1AAECC4A00650035 /* Roxas.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFEC732C1AAECC4A00650035 /* Roxas.framework */; };
@ -108,7 +107,6 @@
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>"; };
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>"; };
BF2B98E51C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SaveStatesCollectionHeaderView.swift; path = "Pause Menu/Save States/SaveStatesCollectionHeaderView.swift"; sourceTree = "<group>"; };
BF31878A1D489AAA00BD020D /* CheatValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CheatValidator.swift; path = "Pause Menu/Cheats/CheatValidator.swift"; sourceTree = "<group>"; };
BF34FA061CF0F510006624C7 /* EditCheatViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EditCheatViewController.swift; path = "Pause Menu/Cheats/EditCheatViewController.swift"; sourceTree = "<group>"; };
@ -138,13 +136,13 @@
BFA2315B1CED10BE0011E35A /* Action.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Action.swift; path = Components/Action.swift; sourceTree = "<group>"; };
BFAA1FEC1B8AA4FA00495943 /* Settings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
BFAA1FF31B8AD7F900495943 /* ControllersSettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControllersSettingsViewController.swift; sourceTree = "<group>"; };
BFB141171BE46934004FBF46 /* GameCollectionViewDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GameCollectionViewDataSource.swift; path = "Collection View/GameCollectionViewDataSource.swift"; sourceTree = "<group>"; };
BFBAA8691D5A483900A29C1B /* DatabaseManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DatabaseManager.swift; sourceTree = "<group>"; };
BFC134E01AAD82460087AD7B /* SNESDeltaCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SNESDeltaCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BFC273171BE6152200D22B05 /* GameCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameCollection.swift; sourceTree = "<group>"; };
BFC9B7381CEFCD34008629BB /* CheatsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CheatsViewController.swift; path = "Pause Menu/Cheats/CheatsViewController.swift"; sourceTree = "<group>"; };
BFCEA67D1D56FF640061A534 /* UIViewControllerContextTransitioning+Conveniences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewControllerContextTransitioning+Conveniences.swift"; sourceTree = "<group>"; };
BFDB28441BC9DA7B001D0C83 /* GamePickerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GamePickerController.swift; sourceTree = "<group>"; };
BFDD04F01D5E2C27002D450E /* GameCollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameCollectionViewController.swift; sourceTree = "<group>"; };
BFDE39391BC0CEDF003F72E8 /* Game.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Game.swift; sourceTree = "<group>"; };
BFEC732C1AAECC4A00650035 /* Roxas.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Roxas.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BFFA71D71AAC406100EE9DD1 /* Delta.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Delta.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -253,7 +251,7 @@
isa = PBXGroup;
children = (
BF107EC31BF413F000E0C32C /* GamesViewController.swift */,
BF27CC961BCC890700A20D89 /* GamesCollectionViewController.swift */,
BFDD04F01D5E2C27002D450E /* GameCollectionViewController.swift */,
BFFC461A1D59820F00AF2CC6 /* Segues */,
);
path = "Game Selection";
@ -299,7 +297,6 @@
children = (
BF7AE81A1C2E984300B1B5BC /* GridCollectionViewCell.swift */,
BF7AE81D1C2E984300B1B5BC /* GridCollectionViewLayout.swift */,
BFB141171BE46934004FBF46 /* GameCollectionViewDataSource.swift */,
);
name = "Collection View";
sourceTree = "<group>";
@ -581,13 +578,12 @@
BFA0D1271D3AE1F600565894 /* GameViewController.swift in Sources */,
BF13A7581D5D2FD9000BB055 /* EmulatorCore+Cheats.swift in Sources */,
BF31878B1D489AAA00BD020D /* CheatValidator.swift in Sources */,
BFB141181BE46934004FBF46 /* GameCollectionViewDataSource.swift in Sources */,
BFFC46201D59823500AF2CC6 /* InitialGamesStoryboardSegue.swift in Sources */,
BFA2315C1CED10BE0011E35A /* Action.swift in Sources */,
BFAA1FF41B8AD7F900495943 /* ControllersSettingsViewController.swift in Sources */,
BF353FF91C5D870B00C1184C /* PauseItem.swift in Sources */,
BF27CC971BCC890700A20D89 /* GamesCollectionViewController.swift in Sources */,
BFBAA86A1D5A483900A29C1B /* DatabaseManager.swift in Sources */,
BFDD04F11D5E2C27002D450E /* GameCollectionViewController.swift in Sources */,
BFFA71DD1AAC406100EE9DD1 /* AppDelegate.swift in Sources */,
BF7AE81E1C2E984300B1B5BC /* GridCollectionViewCell.swift in Sources */,
BF34FA111CF1899D006624C7 /* CheatTextView.swift in Sources */,
@ -601,7 +597,6 @@
BF762EAB1BC1B076002C8866 /* NSManagedObject+Conveniences.swift in Sources */,
BFC9B7391CEFCD34008629BB /* CheatsViewController.swift in Sources */,
BF353FFF1C5DA3C500C1184C /* PausePresentationController.swift in Sources */,
BF02BD001D361BD1000892F2 /* NSFetchedResultsController+Conveniences.m in Sources */,
BFFC464C1D5998D600AF2CC6 /* CheatTableViewCell.swift in Sources */,
BF7AE80A1C2E8C7600B1B5BC /* UIColor+Delta.swift in Sources */,
BF090CF41B490D8300DCAB45 /* UIDevice+Vibration.m in Sources */,
@ -613,6 +608,7 @@
BF107EC41BF413F000E0C32C /* GamesViewController.swift in Sources */,
BF172AEB1C68986300C26774 /* NSManagedObjectContext+Conveniences.swift in Sources */,
BF13A7561D5D29B0000BB055 /* PreviewGameViewController.swift in Sources */,
BFDD04EF1D5E27DB002D450E /* NSFetchedResultsController+Conveniences.m in Sources */,
BFCEA67E1D56FF640061A534 /* UIViewControllerContextTransitioning+Conveniences.swift in Sources */,
BFFC461E1D59823500AF2CC6 /* GamesPresentationController.swift in Sources */,
BF5E7F441B9A650B00AE44F8 /* SettingsViewController.swift in Sources */,

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11185.3" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="yhz-fF-D91">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11191" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="yhz-fF-D91">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11151.4"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11156"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -20,7 +20,7 @@
<subviews>
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tmn-gd-5UN">
<connections>
<segue destination="tpK-ou-yEA" kind="embed" id="cjU-nW-cHY"/>
<segue destination="tpK-ou-yEA" kind="embed" identifier="embedPageViewController" id="cjU-nW-cHY"/>
</connections>
</containerView>
</subviews>
@ -49,10 +49,10 @@
</objects>
<point key="canvasLocation" x="1036" y="1002"/>
</scene>
<!--Games Collection View Controller-->
<!--Game Collection View Controller-->
<scene sceneID="qNA-NP-TiF">
<objects>
<collectionViewController storyboardIdentifier="gamesCollectionViewController" clearsSelectionOnViewWillAppear="NO" id="kqu-75-owz" customClass="GamesCollectionViewController" customModule="Delta" customModuleProvider="target" sceneMemberID="viewController">
<collectionViewController storyboardIdentifier="gameCollectionViewController" clearsSelectionOnViewWillAppear="NO" id="kqu-75-owz" customClass="GameCollectionViewController" customModule="Delta" customModuleProvider="target" sceneMemberID="viewController">
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="OIq-Z8-kxO">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@ -64,16 +64,13 @@
<inset key="sectionInset" minX="0.0" minY="20" maxX="0.0" maxY="20"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="GameCell" id="ioT-sh-j8y" customClass="GridCollectionViewCell" customModule="Delta" customModuleProvider="target">
<frame key="frameInset" minY="20" width="100" height="100"/>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="Cell" id="ioT-sh-j8y" customClass="GridCollectionViewCell" customModule="Delta" customModuleProvider="target">
<rect key="frame" x="0.0" y="20" width="100" height="100"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
<autoresizingMask key="autoresizingMask"/>
</view>
<connections>
<segue destination="X2o-q6-XD5" kind="unwind" unwindAction="unwindFromGamesViewControllerWith:" id="Cxx-73-8KV"/>
</connections>
</collectionViewCell>
</cells>
<connections>
@ -81,6 +78,9 @@
<outlet property="delegate" destination="kqu-75-owz" id="B0G-y1-UrU"/>
</connections>
</collectionView>
<connections>
<segue destination="X2o-q6-XD5" kind="unwind" identifier="unwindFromGames" unwindAction="unwindFromGamesViewControllerWith:" id="k8C-Xn-maU"/>
</connections>
</collectionViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="bW1-t8-idm" userLabel="First Responder" sceneMemberID="firstResponder"/>
<exit id="X2o-q6-XD5" userLabel="Exit" sceneMemberID="exit"/>

View File

@ -0,0 +1,152 @@
//
// GameCollectionViewController.swift
// Delta
//
// Created by Riley Testut on 8/12/16.
// Copyright © 2016 Riley Testut. All rights reserved.
//
import UIKit
import Roxas
class GameCollectionViewController: UICollectionViewController
{
var gameCollection: GameCollection! {
didSet {
self.title = self.gameCollection.shortName
self.updateDataSource()
}
}
var theme: GamesViewController.Theme = .light {
didSet {
self.collectionView?.reloadData()
}
}
private var dataSource: RSTFetchedResultsCollectionViewDataSource<Game>!
private let prototypeCell = GridCollectionViewCell()
}
//MARK: - UIViewController -
/// UIViewController
extension GameCollectionViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
self.collectionView?.dataSource = self.dataSource
self.collectionView?.delegate = self
let layout = self.collectionViewLayout as! GridCollectionViewLayout
layout.itemWidth = 90
}
override func viewWillAppear(_ animated: Bool)
{
self.dataSource.fetchedResultsController.performFetchIfNeeded()
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
//MARK: - Segues -
/// Segues
extension GameCollectionViewController
{
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
{
guard let identifier = segue.identifier, identifier == "unwindFromGames" else { return }
let destinationViewController = segue.destination as! GameViewController
let cell = sender as! UICollectionViewCell
let indexPath = self.collectionView?.indexPath(for: cell)
let game = self.dataSource.fetchedResultsController.object(at: indexPath!)
destinationViewController.game = game
}
}
//MARK: - Configure Cells -
/// Configure Cells
private extension GameCollectionViewController
{
func updateDataSource()
{
let fetchRequest = Game.rst_fetchRequest() as! NSFetchRequest<Game>
fetchRequest.predicate = NSPredicate(format: "ANY %K == %@", #keyPath(Game.gameCollections), self.gameCollection)
fetchRequest.sortDescriptors = [NSSortDescriptor(key: #keyPath(Game.name), ascending: true)]
self.dataSource = RSTFetchedResultsCollectionViewDataSource(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.shared.viewContext)
self.dataSource.cellIdentifierHandler = { _ in RSTGenericCellIdentifier }
self.dataSource.cellConfigurationHandler = { [unowned self] (cell, indexPath) in
self.configure(cell as! GridCollectionViewCell, for: indexPath)
}
}
}
//MARK: - Configure Cells -
/// Configure Cells
private extension GameCollectionViewController
{
func configure(_ cell: GridCollectionViewCell, for indexPath: IndexPath)
{
let game = self.dataSource.fetchedResultsController.object(at: indexPath)
cell.maximumImageSize = CGSize(width: 90, height: 90)
cell.textLabel.text = game.name
cell.imageView.image = UIImage(named: "BoxArt")
switch self.theme
{
case .light:
cell.textLabel.textColor = UIColor.darkText
cell.isTextLabelVibrancyEnabled = false
cell.isImageViewVibrancyEnabled = false
case .dark:
cell.textLabel.textColor = UIColor.white
cell.isTextLabelVibrancyEnabled = true
cell.isImageViewVibrancyEnabled = true
}
}
}
//MARK: - UICollectionViewDelegate -
/// UICollectionViewDelegate
extension GameCollectionViewController
{
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
let cell = collectionView.cellForItem(at: indexPath)
self.performSegue(withIdentifier: "unwindFromGames", sender: cell)
}
}
//MARK: - UICollectionViewDelegateFlowLayout -
/// UICollectionViewDelegateFlowLayout
extension GameCollectionViewController: UICollectionViewDelegateFlowLayout
{
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
let collectionViewLayout = collectionView.collectionViewLayout as! GridCollectionViewLayout
let widthConstraint = self.prototypeCell.contentView.widthAnchor.constraint(equalToConstant: collectionViewLayout.itemWidth)
widthConstraint.isActive = true
defer { widthConstraint.isActive = false }
self.configure(self.prototypeCell, for: indexPath)
let size = self.prototypeCell.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
return size
}
}

View File

@ -1,107 +0,0 @@
//
// GamesCollectionViewController.swift
// Delta
//
// Created by Riley Testut on 10/12/15.
// Copyright © 2015 Riley Testut. All rights reserved.
//
import UIKit
import CoreData
import DeltaCore
class GamesCollectionViewController: UICollectionViewController
{
var theme: GamesViewController.Theme = .light {
didSet {
self.collectionView?.reloadData()
}
}
weak var segueHandler: UIViewController?
var gameCollection: GameCollection! {
didSet
{
self.dataSource.supportedGameCollectionIdentifiers = [self.gameCollection.identifier]
self.title = self.gameCollection.shortName
}
}
let dataSource = GameCollectionViewDataSource()
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
self.dataSource.fetchedResultsController.delegate = self
self.dataSource.cellConfigurationHandler = { [unowned self] (cell, game) in
self.configureCell(cell, game: game)
}
}
override func viewDidLoad()
{
super.viewDidLoad()
self.collectionView?.dataSource = self.dataSource
self.collectionView?.delegate = self.dataSource
if let layout = self.collectionViewLayout as? GridCollectionViewLayout
{
layout.itemWidth = 90
}
}
override func viewWillAppear(_ animated: Bool)
{
self.dataSource.update()
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Navigation -
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
{
self.segueHandler?.prepare(for: segue, sender: sender)
}
// MARK: - Collection View -
private func configureCell(_ cell: GridCollectionViewCell, game: Game)
{
cell.maximumImageSize = CGSize(width: 90, height: 90)
cell.textLabel.text = game.name
cell.imageView.image = UIImage(named: "BoxArt")
switch self.theme
{
case .light:
cell.textLabel.textColor = UIColor.darkText
cell.isTextLabelVibrancyEnabled = false
cell.isImageViewVibrancyEnabled = false
case .dark:
cell.textLabel.textColor = UIColor.white
cell.isTextLabelVibrancyEnabled = true
cell.isImageViewVibrancyEnabled = true
}
}
}
extension GamesCollectionViewController: NSFetchedResultsControllerDelegate
{
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
{
self.collectionView?.reloadData()
}
}

View File

@ -43,37 +43,37 @@ class GamesViewController: UIViewController
required init?(coder aDecoder: NSCoder)
{
let fetchRequest = GameCollection.rst_fetchRequest()
fetchRequest.sortDescriptors = [NSSortDescriptor(key: GameCollection.Attributes.index.rawValue, ascending: true)]
fetchRequest.sortDescriptors = [NSSortDescriptor(key: #keyPath(GameCollection.index), ascending: true)]
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.shared.viewContext, sectionNameKeyPath: nil, cacheName: nil)
super.init(coder: aDecoder)
self.fetchedResultsController.delegate = self
self.automaticallyAdjustsScrollViewInsets = false
}
}
//MARK: - UIViewController -
/// UIViewController
extension GamesViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
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, at: 0)
self.pageViewController = self.childViewControllers.first as? UIPageViewController
self.pageViewController.dataSource = self
self.pageViewController.delegate = self
self.pageViewController.view.isHidden = true
self.pageControl = UIPageControl()
self.pageControl.translatesAutoresizingMaskIntoConstraints = false
self.pageControl.hidesForSinglePage = false
self.pageControl.numberOfPages = 3
self.pageControl.currentPageIndicatorTintColor = UIColor.purple
self.pageControl.currentPageIndicatorTintColor = UIColor.deltaPurpleColor()
self.pageControl.pageIndicatorTintColor = UIColor.lightGray
self.navigationController?.toolbar.addSubview(self.pageControl)
@ -85,17 +85,8 @@ class GamesViewController: UIViewController
{
super.viewWillAppear(animated)
if self.fetchedResultsController.fetchedObjects == nil
if self.fetchedResultsController.performFetchIfNeeded()
{
do
{
try self.fetchedResultsController.performFetch()
}
catch let error as NSError
{
print(error)
}
self.updateSections()
}
}
@ -104,7 +95,7 @@ class GamesViewController: UIViewController
{
super.viewDidLayoutSubviews()
if let viewControllers = self.pageViewController.viewControllers as? [GamesCollectionViewController]
if let viewControllers = self.pageViewController.viewControllers as? [GameCollectionViewController]
{
for viewController in viewControllers
{
@ -113,7 +104,8 @@ class GamesViewController: UIViewController
}
}
override func didReceiveMemoryWarning() {
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@ -126,14 +118,12 @@ extension GamesViewController
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
{
guard let sourceViewController = segue.source as? GamesCollectionViewController else { return }
guard let destinationViewController = segue.destination as? GameViewController else { return }
guard let cell = sender as? UICollectionViewCell else { return }
guard let identifier = segue.identifier, identifier == "embedPageViewController" else { return }
let indexPath = sourceViewController.collectionView?.indexPath(for: cell)
let game = sourceViewController.dataSource.fetchedResultsController.object(at: indexPath!) as! Game
destinationViewController.game = game
self.pageViewController = segue.destination as! UIPageViewController
self.pageViewController.dataSource = self
self.pageViewController.delegate = self
self.pageViewController.view.isHidden = true
}
@IBAction private func unwindFromSettingsViewController(_ segue: UIStoryboardSegue)
@ -160,9 +150,12 @@ private extension GamesViewController
self.navigationController?.toolbar.barStyle = .blackTranslucent
}
if let collectionViewController = self.pageViewController.viewControllers?.first as? UICollectionViewController
if let viewControllers = self.pageViewController.viewControllers as? [GameCollectionViewController]
{
collectionViewController.collectionView?.reloadData()
for collectionViewController in viewControllers
{
collectionViewController.theme = self.theme
}
}
}
}
@ -170,7 +163,7 @@ private extension GamesViewController
// MARK: - Helper Methods -
private extension GamesViewController
{
func viewControllerForIndex(_ index: Int) -> GamesCollectionViewController?
func viewControllerForIndex(_ index: Int) -> GameCollectionViewController?
{
guard let pages = self.fetchedResultsController.sections?.first?.numberOfObjects, pages > 0 else { return nil }
@ -185,10 +178,8 @@ private extension GamesViewController
let indexPath = IndexPath(row: safeIndex, section: 0)
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "gamesCollectionViewController") as! GamesCollectionViewController
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "gameCollectionViewController") as! GameCollectionViewController
viewController.gameCollection = self.fetchedResultsController.object(at: indexPath) as! GameCollection
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
viewController.segueHandler = self
viewController.theme = self.theme
return viewController
@ -201,7 +192,7 @@ private extension GamesViewController
var resetPageViewController = false
if let viewController = pageViewController.viewControllers?.first as? GamesCollectionViewController, let gameCollection = viewController.gameCollection
if let viewController = pageViewController.viewControllers?.first as? GameCollectionViewController, let gameCollection = viewController.gameCollection
{
if let index = self.fetchedResultsController.fetchedObjects?.index(where: { $0 as! GameCollection == gameCollection })
{
@ -252,7 +243,7 @@ private extension GamesViewController
}
//MARK: - Importing -
// Importing
/// Importing
extension GamesViewController: GamePickerControllerDelegate
{
@IBAction private func importFiles()
@ -270,7 +261,7 @@ extension GamesViewController: GamePickerControllerDelegate
}
//MARK: - UIPageViewController -
// UIPageViewController
/// UIPageViewController
extension GamesViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate
{
//MARK: - UIPageViewControllerDataSource
@ -287,9 +278,19 @@ extension GamesViewController: UIPageViewControllerDataSource, UIPageViewControl
}
//MARK: - UIPageViewControllerDelegate
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController])
{
guard let viewControllers = pendingViewControllers as? [GameCollectionViewController] else { return }
for viewController in viewControllers
{
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
}
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool)
{
if let viewController = pageViewController.viewControllers?.first as? GamesCollectionViewController, let gameCollection = viewController.gameCollection
if let viewController = pageViewController.viewControllers?.first as? GameCollectionViewController, let gameCollection = viewController.gameCollection
{
let index = self.fetchedResultsController.fetchedObjects?.index(where: { $0 as! GameCollection == gameCollection }) ?? 0
self.pageControl.currentPage = index
@ -300,7 +301,7 @@ extension GamesViewController: UIPageViewControllerDataSource, UIPageViewControl
}
//MARK: - NSFetchedResultsControllerDelegate -
// NSFetchedResultsControllerDelegate
/// NSFetchedResultsControllerDelegate
extension GamesViewController: NSFetchedResultsControllerDelegate
{
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)

2
External/Roxas vendored

@ -1 +1 @@
Subproject commit f9aa36cc59b228bf8182044da017f39b79b7475a
Subproject commit f0661f78b095212ed2f564a4bbf1c1f6c9c50384