Updates syntax to Swift 3 beta 2 via Xcode migrator

This commit is contained in:
Riley Testut 2016-07-13 01:28:38 -05:00
parent e6585ec177
commit 9ce16a2a9d
34 changed files with 744 additions and 729 deletions

View File

@ -46,23 +46,23 @@ class GameCollectionViewDataSource: NSObject
let fetchRequest = Game.fetchRequest() let fetchRequest = Game.fetchRequest()
var predicates: [NSPredicate] = [] var predicates: [Predicate] = []
if let identifiers = self.supportedGameCollectionIdentifiers if let identifiers = self.supportedGameCollectionIdentifiers
{ {
for identifier in identifiers for identifier in identifiers
{ {
let predicate = NSPredicate(format: "SUBQUERY(%K, $x, $x.%K == %@).@count > 0", Game.Attributes.gameCollections.rawValue, GameCollection.Attributes.identifier.rawValue, identifier) let predicate = Predicate(format: "SUBQUERY(%K, $x, $x.%K == %@).@count > 0", Game.Attributes.gameCollections.rawValue, GameCollection.Attributes.identifier.rawValue, identifier)
predicates.append(predicate) predicates.append(predicate)
} }
} }
if predicates.count > 0 if predicates.count > 0
{ {
fetchRequest.predicate = NSCompoundPredicate(orPredicateWithSubpredicates: predicates) fetchRequest.predicate = CompoundPredicate(orPredicateWithSubpredicates: predicates)
} }
fetchRequest.sortDescriptors = [NSSortDescriptor(key: Game.Attributes.typeIdentifier.rawValue, ascending: true), NSSortDescriptor(key: Game.Attributes.name.rawValue, ascending: true)] fetchRequest.sortDescriptors = [SortDescriptor(key: Game.Attributes.typeIdentifier.rawValue, ascending: true), SortDescriptor(key: Game.Attributes.name.rawValue, ascending: true)]
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: Game.Attributes.typeIdentifier.rawValue, cacheName: nil) self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: Game.Attributes.typeIdentifier.rawValue, cacheName: nil)
self.fetchedResultsController.delegate = previousDelegate self.fetchedResultsController.delegate = previousDelegate
@ -72,9 +72,9 @@ class GameCollectionViewDataSource: NSObject
// MARK: - Collection View - // MARK: - Collection View -
private func configureCell(cell: GridCollectionViewCell, forIndexPath indexPath: NSIndexPath) private func configureCell(_ cell: GridCollectionViewCell, forIndexPath indexPath: IndexPath)
{ {
let game = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Game let game = self.fetchedResultsController.object(at: indexPath) as! Game
if let handler = self.cellConfigurationHandler if let handler = self.cellConfigurationHandler
{ {
@ -85,20 +85,20 @@ class GameCollectionViewDataSource: NSObject
extension GameCollectionViewDataSource: UICollectionViewDataSource extension GameCollectionViewDataSource: UICollectionViewDataSource
{ {
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int func numberOfSections(in collectionView: UICollectionView) -> Int
{ {
return self.fetchedResultsController.sections?.count ?? 0 return self.fetchedResultsController.sections?.count ?? 0
} }
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{ {
let count = self.fetchedResultsController.sections?[section].numberOfObjects ?? 0 let count = self.fetchedResultsController.sections?[section].numberOfObjects ?? 0
return count return count
} }
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{ {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("GameCell", forIndexPath: indexPath) as! GridCollectionViewCell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "GameCell", for: indexPath) as! GridCollectionViewCell
self.configureCell(cell, forIndexPath: indexPath) self.configureCell(cell, forIndexPath: indexPath)
@ -108,18 +108,18 @@ extension GameCollectionViewDataSource: UICollectionViewDataSource
extension GameCollectionViewDataSource: UICollectionViewDelegate extension GameCollectionViewDataSource: UICollectionViewDelegate
{ {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize
{ {
let collectionViewLayout = collectionView.collectionViewLayout as! GridCollectionViewLayout let collectionViewLayout = collectionView.collectionViewLayout as! GridCollectionViewLayout
let widthConstraint = self.prototypeCell.contentView.widthAnchor.constraintEqualToConstant(collectionViewLayout.itemWidth) let widthConstraint = self.prototypeCell.contentView.widthAnchor.constraint(equalToConstant: collectionViewLayout.itemWidth)
widthConstraint.active = true widthConstraint.isActive = true
self.configureCell(self.prototypeCell, forIndexPath: indexPath) self.configureCell(self.prototypeCell, forIndexPath: indexPath)
let size = self.prototypeCell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize) let size = self.prototypeCell.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
widthConstraint.active = false widthConstraint.isActive = false
return size return size
} }

View File

@ -44,44 +44,44 @@ class GridCollectionViewCell: UICollectionViewCell
private func configureSubviews() private func configureSubviews()
{ {
// Fix super annoying Unsatisfiable Constraints message in debugger by setting autoresizingMask // Fix super annoying Unsatisfiable Constraints message in debugger by setting autoresizingMask
self.contentView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] self.contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.clipsToBounds = false self.clipsToBounds = false
self.contentView.clipsToBounds = false self.contentView.clipsToBounds = false
self.imageView.translatesAutoresizingMaskIntoConstraints = false self.imageView.translatesAutoresizingMaskIntoConstraints = false
self.imageView.contentMode = .ScaleAspectFit self.imageView.contentMode = .scaleAspectFit
#if os(tvOS) #if os(tvOS)
self.imageView.adjustsImageWhenAncestorFocused = true self.imageView.adjustsImageWhenAncestorFocused = true
#endif #endif
self.contentView.addSubview(self.imageView) self.contentView.addSubview(self.imageView)
self.textLabel.translatesAutoresizingMaskIntoConstraints = false self.textLabel.translatesAutoresizingMaskIntoConstraints = false
self.textLabel.font = UIFont.boldSystemFontOfSize(12) self.textLabel.font = UIFont.boldSystemFont(ofSize: 12)
self.textLabel.textAlignment = .Center self.textLabel.textAlignment = .center
self.textLabel.numberOfLines = 0 self.textLabel.numberOfLines = 0
self.contentView.addSubview(self.textLabel) self.contentView.addSubview(self.textLabel)
// Auto Layout // Auto Layout
self.imageView.topAnchor.constraintEqualToAnchor(self.contentView.topAnchor).active = true self.imageView.topAnchor.constraint(equalTo: self.contentView.topAnchor).isActive = true
self.imageView.centerXAnchor.constraintEqualToAnchor(self.contentView.centerXAnchor).active = true self.imageView.centerXAnchor.constraint(equalTo: self.contentView.centerXAnchor).isActive = true
self.imageViewWidthConstraint = self.imageView.widthAnchor.constraintEqualToConstant(self.maximumImageSize.width) self.imageViewWidthConstraint = self.imageView.widthAnchor.constraint(equalToConstant: self.maximumImageSize.width)
self.imageViewWidthConstraint.active = true self.imageViewWidthConstraint.isActive = true
self.imageViewHeightConstraint = self.imageView.heightAnchor.constraintEqualToConstant(self.maximumImageSize.height) self.imageViewHeightConstraint = self.imageView.heightAnchor.constraint(equalToConstant: self.maximumImageSize.height)
self.imageViewHeightConstraint.active = true self.imageViewHeightConstraint.isActive = true
self.textLabel.trailingAnchor.constraintEqualToAnchor(self.contentView.trailingAnchor).active = true self.textLabel.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor).isActive = true
self.textLabel.leadingAnchor.constraintEqualToAnchor(self.contentView.leadingAnchor).active = true self.textLabel.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor).isActive = true
self.textLabelBottomAnchorConstraint = self.textLabel.bottomAnchor.constraintEqualToAnchor(self.contentView.bottomAnchor) self.textLabelBottomAnchorConstraint = self.textLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor)
self.textLabelBottomAnchorConstraint.active = true self.textLabelBottomAnchorConstraint.isActive = true
self.textLabelVerticalSpacingConstraint = self.textLabel.topAnchor.constraintEqualToAnchor(self.imageView.bottomAnchor) self.textLabelVerticalSpacingConstraint = self.textLabel.topAnchor.constraint(equalTo: self.imageView.bottomAnchor)
self.textLabelVerticalSpacingConstraint.active = true self.textLabelVerticalSpacingConstraint.isActive = true
#if os(tvOS) #if os(tvOS)
@ -90,37 +90,37 @@ class GridCollectionViewCell: UICollectionViewCell
self.textLabelFocusedVerticalSpacingConstraint = self.textLabel.topAnchor.constraintEqualToAnchor(self.imageView.focusedFrameGuide.bottomAnchor, constant: 0) self.textLabelFocusedVerticalSpacingConstraint = self.textLabel.topAnchor.constraintEqualToAnchor(self.imageView.focusedFrameGuide.bottomAnchor, constant: 0)
self.textLabelFocusedVerticalSpacingConstraint?.active = true self.textLabelFocusedVerticalSpacingConstraint?.active = true
#else #else
self.textLabelVerticalSpacingConstraint.active = true self.textLabelVerticalSpacingConstraint.isActive = true
#endif #endif
self.updateMaximumImageSize() self.updateMaximumImageSize()
} }
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator)
{ {
super.didUpdateFocusInContext(context, withAnimationCoordinator: coordinator) super.didUpdateFocus(in: context, with: coordinator)
coordinator.addCoordinatedAnimations({ coordinator.addCoordinatedAnimations({
if context.nextFocusedView == self if context.nextFocusedView == self
{ {
self.textLabelBottomAnchorConstraint?.active = false self.textLabelBottomAnchorConstraint?.isActive = false
self.textLabelVerticalSpacingConstraint.active = false self.textLabelVerticalSpacingConstraint.isActive = false
self.textLabelFocusedVerticalSpacingConstraint?.active = true self.textLabelFocusedVerticalSpacingConstraint?.isActive = true
self.textLabel.textColor = UIColor.whiteColor() self.textLabel.textColor = UIColor.white()
} }
else else
{ {
self.textLabelFocusedVerticalSpacingConstraint?.active = false self.textLabelFocusedVerticalSpacingConstraint?.isActive = false
self.textLabelBottomAnchorConstraint?.active = true self.textLabelBottomAnchorConstraint?.isActive = true
self.textLabelVerticalSpacingConstraint.active = true self.textLabelVerticalSpacingConstraint.isActive = true
self.textLabel.textColor = UIColor.blackColor() self.textLabel.textColor = UIColor.black()
} }
self.layoutIfNeeded() self.layoutIfNeeded()

View File

@ -29,7 +29,7 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
} }
} }
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?
{ {
guard let collectionView = self.collectionView else { return nil } guard let collectionView = self.collectionView else { return nil }
@ -39,7 +39,7 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
self.sectionInset.left = interitemSpacing self.sectionInset.left = interitemSpacing
self.sectionInset.right = interitemSpacing self.sectionInset.right = interitemSpacing
let layoutAttributes = super.layoutAttributesForElementsInRect(rect)?.map({ $0.copy() }) as! [UICollectionViewLayoutAttributes] let layoutAttributes = super.layoutAttributesForElements(in: rect)?.map({ $0.copy() }) as! [UICollectionViewLayoutAttributes]
var minimumY: CGFloat? = nil var minimumY: CGFloat? = nil
var maximumY: CGFloat? = nil var maximumY: CGFloat? = nil
@ -47,9 +47,9 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
var isSingleRow = true var isSingleRow = true
for (index, attributes) in layoutAttributes.enumerate() for (index, attributes) in layoutAttributes.enumerated()
{ {
guard attributes.representedElementCategory == .Cell else { continue } 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
@ -103,7 +103,7 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
{ {
let spacing = (collectionView.bounds.width - (self.itemWidth * CGFloat(tempLayoutAttributes.count))) / (CGFloat(tempLayoutAttributes.count) + 1.0) let spacing = (collectionView.bounds.width - (self.itemWidth * CGFloat(tempLayoutAttributes.count))) / (CGFloat(tempLayoutAttributes.count) + 1.0)
for (index, layoutAttributes) in tempLayoutAttributes.enumerate() for (index, layoutAttributes) in tempLayoutAttributes.enumerated()
{ {
layoutAttributes.frame.origin.x = spacing + (spacing + self.itemWidth) * CGFloat(index) layoutAttributes.frame.origin.x = spacing + (spacing + self.itemWidth) * CGFloat(index)
} }
@ -117,7 +117,7 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
private extension GridCollectionViewLayout private extension GridCollectionViewLayout
{ {
func alignLayoutAttributes(layoutAttributes: [UICollectionViewLayoutAttributes], toMinimumY minimumY: CGFloat) func alignLayoutAttributes(_ layoutAttributes: [UICollectionViewLayoutAttributes], toMinimumY minimumY: CGFloat)
{ {
for attributes in layoutAttributes for attributes in layoutAttributes
{ {

View File

@ -12,10 +12,10 @@ extension Action
{ {
enum Style enum Style
{ {
case Default case `default`
case Cancel case cancel
case Destructive case destructive
case Selected case selected
} }
} }
@ -25,9 +25,9 @@ extension Action.Style
{ {
switch self switch self
{ {
case .Default, .Selected: return .Default case .default, .selected: return .default
case .Cancel: return .Cancel case .cancel: return .cancel
case .Destructive: return .Destructive case .destructive: return .destructive
} }
} }
@ -35,9 +35,9 @@ extension Action.Style
{ {
switch self switch self
{ {
case .Default, .Cancel: return .Default case .default, .cancel: return .default
case .Destructive: return .Destructive case .destructive: return .destructive
case .Selected: return .Selected case .selected: return .selected
} }
} }
} }
@ -46,7 +46,7 @@ struct Action
{ {
let title: String let title: String
let style: Style let style: Style
let action: (Action -> Void)? let action: ((Action) -> Void)?
var alertAction: UIAlertAction var alertAction: UIAlertAction
{ {

View File

@ -50,6 +50,6 @@ class BoxArtImageView: UIImageView
self.adjustsImageWhenAncestorFocused = true self.adjustsImageWhenAncestorFocused = true
#endif #endif
self.contentMode = .ScaleAspectFit self.contentMode = .scaleAspectFit
} }
} }

View File

@ -13,9 +13,9 @@ import Roxas
public class LoadImageOperation: RSTOperation public class LoadImageOperation: RSTOperation
{ {
public let URL: NSURL public let URL: Foundation.URL
public var completionHandler: (UIImage? -> Void)? { public var completionHandler: ((UIImage?) -> Void)? {
didSet { didSet {
self.completionBlock = { self.completionBlock = {
rst_dispatch_sync_on_main_thread() { rst_dispatch_sync_on_main_thread() {
@ -25,16 +25,16 @@ public class LoadImageOperation: RSTOperation
} }
} }
public var imageCache: NSCache? { public var imageCache: Cache<AnyObject, AnyObject>? {
didSet { didSet {
// Ensures if an image is cached, it will be returned immediately, to prevent temporary flash of placeholder image // Ensures if an image is cached, it will be returned immediately, to prevent temporary flash of placeholder image
self.immediate = self.imageCache?.objectForKey(self.URL) != nil self.isImmediate = self.imageCache?.object(forKey: self.URL) != nil
} }
} }
private var image: UIImage? private var image: UIImage?
public init(URL: NSURL) public init(URL: Foundation.URL)
{ {
self.URL = URL self.URL = URL
@ -46,9 +46,9 @@ public extension LoadImageOperation
{ {
override func main() override func main()
{ {
guard !self.cancelled else { return } guard !self.isCancelled else { return }
if let cachedImage = self.imageCache?.objectForKey(self.URL) as? UIImage if let cachedImage = self.imageCache?.object(forKey: self.URL) as? UIImage
{ {
self.image = cachedImage self.image = cachedImage
return return
@ -58,11 +58,11 @@ public extension LoadImageOperation
if let imageSource = CGImageSourceCreateWithURL(self.URL, options), quartzImage = CGImageSourceCreateImageAtIndex(imageSource, 0, options) if let imageSource = CGImageSourceCreateWithURL(self.URL, options), quartzImage = CGImageSourceCreateImageAtIndex(imageSource, 0, options)
{ {
let loadedImage = UIImage(CGImage: quartzImage) let loadedImage = UIImage(cgImage: quartzImage)
// Force decompression of image // Force decompression of image
UIGraphicsBeginImageContextWithOptions(CGSize(width: 1, height: 1), true, 1.0) UIGraphicsBeginImageContextWithOptions(CGSize(width: 1, height: 1), true, 1.0)
loadedImage.drawAtPoint(CGPoint.zero) loadedImage.draw(at: CGPoint.zero)
UIGraphicsEndImageContext() UIGraphicsEndImageContext()
self.imageCache?.setObject(loadedImage, forKey: self.URL) self.imageCache?.setObject(loadedImage, forKey: self.URL)

View File

@ -29,46 +29,46 @@ class DatabaseManager
private init() private init()
{ {
let modelURL = NSBundle.mainBundle().URLForResource("Model", withExtension: "momd") let modelURL = Bundle.main.urlForResource("Model", withExtension: "momd")
let managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL!) let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL!)
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel!) let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel!)
self.privateManagedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType) self.privateManagedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
self.privateManagedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator self.privateManagedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator
self.privateManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy self.privateManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
self.managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType) self.managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
self.managedObjectContext.parentContext = self.privateManagedObjectContext self.managedObjectContext.parent = self.privateManagedObjectContext
self.managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy self.managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
self.validationManagedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType) self.validationManagedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
self.validationManagedObjectContext.parentContext = self.managedObjectContext self.validationManagedObjectContext.parent = self.managedObjectContext
self.validationManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy self.validationManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(DatabaseManager.managedObjectContextWillSave(_:)), name: NSManagedObjectContextWillSaveNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(DatabaseManager.managedObjectContextWillSave(_:)), name: NSNotification.Name.NSManagedObjectContextWillSave, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(DatabaseManager.managedObjectContextDidSave(_:)), name: NSManagedObjectContextDidSaveNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(DatabaseManager.managedObjectContextDidSave(_:)), name: NSNotification.Name.NSManagedObjectContextDidSave, object: nil)
} }
func startWithCompletion(completionBlock: ((performingMigration: Bool) -> Void)?) func startWithCompletion(_ completionBlock: ((performingMigration: Bool) -> Void)?)
{ {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) { DispatchQueue.global(attributes: DispatchQueue.GlobalAttributes.qosUserInitiated).async {
let storeURL = DatabaseManager.databaseDirectoryURL.URLByAppendingPathComponent("Delta.sqlite") let storeURL = try! DatabaseManager.databaseDirectoryURL.appendingPathComponent("Delta.sqlite")
let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true] let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
var performingMigration = false var performingMigration = false
if let sourceMetadata = try? NSPersistentStoreCoordinator.metadataForPersistentStoreOfType(NSSQLiteStoreType, URL: storeURL, options: options), if let sourceMetadata = try? NSPersistentStoreCoordinator.metadataForPersistentStore(ofType: NSSQLiteStoreType, at: storeURL, options: options),
managedObjectModel = self.privateManagedObjectContext.persistentStoreCoordinator?.managedObjectModel managedObjectModel = self.privateManagedObjectContext.persistentStoreCoordinator?.managedObjectModel
{ {
performingMigration = !managedObjectModel.isConfiguration(nil, compatibleWithStoreMetadata: sourceMetadata) performingMigration = !managedObjectModel.isConfiguration(withName: nil, compatibleWithStoreMetadata: sourceMetadata)
} }
do do
{ {
try self.privateManagedObjectContext.persistentStoreCoordinator?.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: options) try self.privateManagedObjectContext.persistentStoreCoordinator?.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: options)
} }
catch let error as NSError catch let error as NSError
{ {
@ -94,16 +94,16 @@ class DatabaseManager
// MARK: - Importing - // MARK: - Importing -
/// Importing /// Importing
func importGamesAtURLs(URLs: [NSURL], withCompletion completion: ([String] -> Void)?) func importGamesAtURLs(_ URLs: [URL], withCompletion completion: (([String]) -> Void)?)
{ {
let managedObjectContext = self.backgroundManagedObjectContext() let managedObjectContext = self.backgroundManagedObjectContext()
managedObjectContext.performBlock() { managedObjectContext.perform() {
var identifiers: [String] = [] var identifiers: [String] = []
for URL in URLs for URL in URLs
{ {
let identifier = FileHash.sha1HashOfFileAtPath(URL.path) as String let identifier = FileHash.sha1HashOfFile(atPath: URL.path) as String
var filename = identifier var filename = identifier
if let pathExtension = URL.pathExtension if let pathExtension = URL.pathExtension
@ -112,7 +112,7 @@ class DatabaseManager
} }
let game = Game.insertIntoManagedObjectContext(managedObjectContext) let game = Game.insertIntoManagedObjectContext(managedObjectContext)
game.name = URL.URLByDeletingPathExtension?.lastPathComponent ?? NSLocalizedString("Game", comment: "") game.name = try! URL.deletingPathExtension()?.lastPathComponent ?? NSLocalizedString("Game", comment: "")
game.identifier = identifier game.identifier = identifier
game.filename = filename game.filename = filename
@ -129,17 +129,17 @@ class DatabaseManager
do do
{ {
let destinationURL = DatabaseManager.gamesDirectoryURL.URLByAppendingPathComponent(game.identifier + "." + game.preferredFileExtension) let destinationURL = try! DatabaseManager.gamesDirectoryURL.appendingPathComponent(game.identifier + "." + game.preferredFileExtension)
if let path = destinationURL.path if let path = destinationURL.path
{ {
if NSFileManager.defaultManager().fileExistsAtPath(path) if FileManager.default.fileExists(atPath: path)
{ {
try NSFileManager.defaultManager().removeItemAtURL(URL) try FileManager.default.removeItem(at: URL)
} }
else else
{ {
try NSFileManager.defaultManager().moveItemAtURL(URL, toURL: destinationURL) try FileManager.default.moveItem(at: URL, to: destinationURL)
} }
} }
@ -147,7 +147,7 @@ class DatabaseManager
} }
catch catch
{ {
game.managedObjectContext?.deleteObject(game) game.managedObjectContext?.delete(game)
} }
} }
@ -177,8 +177,8 @@ class DatabaseManager
func backgroundManagedObjectContext() -> NSManagedObjectContext func backgroundManagedObjectContext() -> NSManagedObjectContext
{ {
let managedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType) let managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
managedObjectContext.parentContext = self.validationManagedObjectContext managedObjectContext.parent = self.validationManagedObjectContext
managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
return managedObjectContext return managedObjectContext
@ -187,44 +187,44 @@ class DatabaseManager
extension DatabaseManager extension DatabaseManager
{ {
class var databaseDirectoryURL: NSURL class var databaseDirectoryURL: URL
{ {
let documentsDirectoryURL: NSURL let documentsDirectoryURL: URL
if UIDevice.currentDevice().userInterfaceIdiom == .TV if UIDevice.current().userInterfaceIdiom == .tv
{ {
documentsDirectoryURL = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.CachesDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).first! documentsDirectoryURL = FileManager.default.urlsForDirectory(FileManager.SearchPathDirectory.cachesDirectory, inDomains: FileManager.SearchPathDomainMask.userDomainMask).first!
} }
else else
{ {
documentsDirectoryURL = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).first! documentsDirectoryURL = FileManager.default.urlsForDirectory(FileManager.SearchPathDirectory.documentDirectory, inDomains: FileManager.SearchPathDomainMask.userDomainMask).first!
} }
let databaseDirectoryURL = documentsDirectoryURL.URLByAppendingPathComponent("Database") let databaseDirectoryURL = try! documentsDirectoryURL.appendingPathComponent("Database")
self.createDirectoryAtURLIfNeeded(databaseDirectoryURL) self.createDirectoryAtURLIfNeeded(databaseDirectoryURL)
return databaseDirectoryURL return databaseDirectoryURL
} }
class var gamesDirectoryURL: NSURL class var gamesDirectoryURL: URL
{ {
let gamesDirectoryURL = DatabaseManager.databaseDirectoryURL.URLByAppendingPathComponent("Games") let gamesDirectoryURL = try! DatabaseManager.databaseDirectoryURL.appendingPathComponent("Games")
self.createDirectoryAtURLIfNeeded(gamesDirectoryURL) self.createDirectoryAtURLIfNeeded(gamesDirectoryURL)
return gamesDirectoryURL return gamesDirectoryURL
} }
class var saveStatesDirectoryURL: NSURL class var saveStatesDirectoryURL: URL
{ {
let saveStatesDirectoryURL = DatabaseManager.databaseDirectoryURL.URLByAppendingPathComponent("Save States") let saveStatesDirectoryURL = try! DatabaseManager.databaseDirectoryURL.appendingPathComponent("Save States")
self.createDirectoryAtURLIfNeeded(saveStatesDirectoryURL) self.createDirectoryAtURLIfNeeded(saveStatesDirectoryURL)
return saveStatesDirectoryURL return saveStatesDirectoryURL
} }
class func saveStatesDirectoryURLForGame(game: Game) -> NSURL class func saveStatesDirectoryURLForGame(_ game: Game) -> URL
{ {
let gameDirectoryURL = DatabaseManager.saveStatesDirectoryURL.URLByAppendingPathComponent(game.identifier) let gameDirectoryURL = try! DatabaseManager.saveStatesDirectoryURL.appendingPathComponent(game.identifier)
self.createDirectoryAtURLIfNeeded(gameDirectoryURL) self.createDirectoryAtURLIfNeeded(gameDirectoryURL)
return gameDirectoryURL return gameDirectoryURL
@ -239,7 +239,7 @@ private extension DatabaseManager
{ {
let backgroundTaskIdentifier = RSTBeginBackgroundTask("Save Database Task") let backgroundTaskIdentifier = RSTBeginBackgroundTask("Save Database Task")
self.validationManagedObjectContext.performBlockAndWait { self.validationManagedObjectContext.performAndWait {
do do
{ {
@ -252,7 +252,7 @@ private extension DatabaseManager
// Update main managed object context // Update main managed object context
self.managedObjectContext.performBlockAndWait() { self.managedObjectContext.performAndWait() {
do do
{ {
@ -265,7 +265,7 @@ private extension DatabaseManager
// Save to disk // Save to disk
self.privateManagedObjectContext.performBlock() { self.privateManagedObjectContext.perform() {
do do
{ {
@ -287,22 +287,22 @@ private extension DatabaseManager
// MARK: - Validation - // MARK: - Validation -
func validateManagedObjectContextSave(managedObjectContext: NSManagedObjectContext) func validateManagedObjectContextSave(_ managedObjectContext: NSManagedObjectContext)
{ {
// Remove deleted files from disk // Remove deleted files from disk
for object in managedObjectContext.deletedObjects for object in managedObjectContext.deletedObjects
{ {
var fileURLs = Set<NSURL>() var fileURLs = Set<URL>()
let temporaryObject = self.validationManagedObjectContext.objectWithID(object.objectID) let temporaryObject = self.validationManagedObjectContext.object(with: object.objectID)
switch temporaryObject switch temporaryObject
{ {
case let game as Game: case let game as Game:
fileURLs.insert(game.fileURL) fileURLs.insert(game.fileURL as URL)
case let saveState as SaveState: case let saveState as SaveState:
fileURLs.insert(saveState.fileURL) fileURLs.insert(saveState.fileURL as URL)
fileURLs.insert(saveState.imageFileURL) fileURLs.insert(saveState.imageFileURL as URL)
default: break default: break
} }
@ -311,7 +311,7 @@ private extension DatabaseManager
{ {
do do
{ {
try NSFileManager.defaultManager().removeItemAtURL(URL) try FileManager.default.removeItem(at: URL)
} }
catch let error as NSError catch let error as NSError
{ {
@ -321,39 +321,39 @@ private extension DatabaseManager
} }
// Remove empty collections // Remove empty collections
let collections = GameCollection.instancesWithPredicate(NSPredicate(format: "%K.@count == 0", GameCollection.Attributes.games.rawValue), inManagedObjectContext: self.validationManagedObjectContext, type: GameCollection.self) let collections = GameCollection.instancesWithPredicate(Predicate(format: "%K.@count == 0", GameCollection.Attributes.games.rawValue), inManagedObjectContext: self.validationManagedObjectContext, type: GameCollection.self)
for collection in collections for collection in collections
{ {
self.validationManagedObjectContext.deleteObject(collection) self.validationManagedObjectContext.delete(collection)
} }
} }
// MARK: - Notifications - // MARK: - Notifications -
@objc func managedObjectContextWillSave(notification: NSNotification) @objc func managedObjectContextWillSave(_ notification: Notification)
{ {
guard let managedObjectContext = notification.object as? NSManagedObjectContext where managedObjectContext.parentContext == self.validationManagedObjectContext else { return } guard let managedObjectContext = notification.object as? NSManagedObjectContext where managedObjectContext.parent == self.validationManagedObjectContext else { return }
self.validationManagedObjectContext.performBlockAndWait { self.validationManagedObjectContext.performAndWait {
self.validateManagedObjectContextSave(managedObjectContext) self.validateManagedObjectContextSave(managedObjectContext)
} }
} }
@objc func managedObjectContextDidSave(notification: NSNotification) @objc func managedObjectContextDidSave(_ notification: Notification)
{ {
guard let managedObjectContext = notification.object as? NSManagedObjectContext where managedObjectContext.parentContext == self.validationManagedObjectContext else { return } guard let managedObjectContext = notification.object as? NSManagedObjectContext where managedObjectContext.parent == self.validationManagedObjectContext else { return }
self.save() self.save()
} }
// MARK: - File Management - // MARK: - File Management -
class func createDirectoryAtURLIfNeeded(URL: NSURL) class func createDirectoryAtURLIfNeeded(_ URL: Foundation.URL)
{ {
do do
{ {
try NSFileManager.defaultManager().createDirectoryAtURL(URL, withIntermediateDirectories: true, attributes: nil) try FileManager.default.createDirectory(at: URL, withIntermediateDirectories: true, attributes: nil)
} }
catch catch
{ {

View File

@ -59,11 +59,11 @@ class Cheat: NSManagedObject, CheatProtocol
//TODO: Change type to String! when Swift 3 allows it //TODO: Change type to String! when Swift 3 allows it
@NSManaged var name: String? @NSManaged var name: String?
@NSManaged var code: String @NSManaged var code: String
@NSManaged var modifiedDate: NSDate @NSManaged var modifiedDate: Date
@NSManaged var enabled: Bool @NSManaged var enabled: Bool
@NSManaged private(set) var identifier: String @NSManaged private(set) var identifier: String
@NSManaged private(set) var creationDate: NSDate @NSManaged private(set) var creationDate: Date
// Must be optional relationship to satisfy weird Core Data requirement // Must be optional relationship to satisfy weird Core Data requirement
// https://forums.developer.apple.com/thread/20535 // https://forums.developer.apple.com/thread/20535
@ -73,16 +73,16 @@ class Cheat: NSManagedObject, CheatProtocol
{ {
get get
{ {
self.willAccessValueForKey(Attributes.type.rawValue) self.willAccessValue(forKey: Attributes.type.rawValue)
let type = CheatType(rawValue: self.primitiveType.shortValue)! let type = CheatType(rawValue: self.primitiveType.int16Value)!
self.didAccessValueForKey(Attributes.type.rawValue) self.didAccessValue(forKey: Attributes.type.rawValue)
return type return type
} }
set set
{ {
self.willChangeValueForKey(Attributes.type.rawValue) self.willChangeValue(forKey: Attributes.type.rawValue)
self.primitiveType = NSNumber(short: newValue.rawValue) self.primitiveType = NSNumber(value: newValue.rawValue)
self.didChangeValueForKey(Attributes.type.rawValue) self.didChangeValue(forKey: Attributes.type.rawValue)
} }
} }
} }
@ -90,16 +90,16 @@ class Cheat: NSManagedObject, CheatProtocol
extension Cheat extension Cheat
{ {
@NSManaged private var primitiveIdentifier: String @NSManaged private var primitiveIdentifier: String
@NSManaged private var primitiveCreationDate: NSDate @NSManaged private var primitiveCreationDate: Date
@NSManaged private var primitiveModifiedDate: NSDate @NSManaged private var primitiveModifiedDate: Date
@NSManaged private var primitiveType: NSNumber @NSManaged private var primitiveType: NSNumber
override func awakeFromInsert() override func awakeFromInsert()
{ {
super.awakeFromInsert() super.awakeFromInsert()
let identifier = NSUUID().UUIDString let identifier = UUID().uuidString
let date = NSDate() let date = Date()
self.primitiveIdentifier = identifier self.primitiveIdentifier = identifier
self.primitiveCreationDate = date self.primitiveCreationDate = date

View File

@ -33,7 +33,7 @@ extension Game
@objc(Game) @objc(Game)
class Game: NSManagedObject, GameType class Game: NSManagedObject, GameType
{ {
@NSManaged var artworkURL: NSURL? @NSManaged var artworkURL: URL?
@NSManaged var filename: String @NSManaged var filename: String
@NSManaged var identifier: String @NSManaged var identifier: String
@NSManaged var name: String @NSManaged var name: String
@ -42,9 +42,9 @@ class Game: NSManagedObject, GameType
@NSManaged var gameCollections: Set<GameCollection> @NSManaged var gameCollections: Set<GameCollection>
@NSManaged var previewSaveState: SaveState? @NSManaged var previewSaveState: SaveState?
var fileURL: NSURL { var fileURL: URL {
let fileURL = DatabaseManager.gamesDirectoryURL.URLByAppendingPathComponent(self.filename) let fileURL = try! DatabaseManager.gamesDirectoryURL.appendingPathComponent(self.filename)
return fileURL return fileURL!
} }
var preferredFileExtension: String { var preferredFileExtension: String {

View File

@ -54,7 +54,7 @@ class GameCollection: NSManagedObject
} }
} }
class func gameSystemCollectionForPathExtension(pathExtension: String?, inManagedObjectContext managedObjectContext: NSManagedObjectContext) -> GameCollection class func gameSystemCollectionForPathExtension(_ pathExtension: String?, inManagedObjectContext managedObjectContext: NSManagedObjectContext) -> GameCollection
{ {
let identifier: String let identifier: String
let index: Int16 let index: Int16
@ -76,7 +76,7 @@ class GameCollection: NSManagedObject
index = Int16(INT16_MAX) index = Int16(INT16_MAX)
} }
let predicate = NSPredicate(format: "%K == %@", GameCollection.Attributes.identifier.rawValue, identifier) let predicate = Predicate(format: "%K == %@", GameCollection.Attributes.identifier.rawValue, identifier)
var gameCollection = GameCollection.instancesWithPredicate(predicate, inManagedObjectContext: managedObjectContext, type: GameCollection.self).first var gameCollection = GameCollection.instancesWithPredicate(predicate, inManagedObjectContext: managedObjectContext, type: GameCollection.self).first
if gameCollection == nil if gameCollection == nil

View File

@ -28,9 +28,9 @@ extension SaveState
@objc enum Type: Int16 @objc enum Type: Int16
{ {
case Auto case auto
case General case general
case Locked case locked
} }
} }
@ -38,12 +38,12 @@ extension SaveState
class SaveState: NSManagedObject, SaveStateType class SaveState: NSManagedObject, SaveStateType
{ {
@NSManaged var name: String? @NSManaged var name: String?
@NSManaged var modifiedDate: NSDate @NSManaged var modifiedDate: Date
@NSManaged var type: Type @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
@NSManaged private(set) var creationDate: NSDate @NSManaged private(set) var creationDate: Date
// Must be optional relationship to satisfy weird Core Data requirement // Must be optional relationship to satisfy weird Core Data requirement
// https://forums.developer.apple.com/thread/20535 // https://forums.developer.apple.com/thread/20535
@ -51,14 +51,14 @@ class SaveState: NSManagedObject, SaveStateType
@NSManaged var previewGame: Game? @NSManaged var previewGame: Game?
var fileURL: NSURL { var fileURL: URL {
let fileURL = DatabaseManager.saveStatesDirectoryURLForGame(self.game).URLByAppendingPathComponent(self.filename) let fileURL = try! DatabaseManager.saveStatesDirectoryURLForGame(self.game).appendingPathComponent(self.filename)
return fileURL return fileURL
} }
var imageFileURL: NSURL { var imageFileURL: URL {
let imageFilename = (self.filename as NSString).stringByDeletingPathExtension + ".png" let imageFilename = (self.filename as NSString).deletingPathExtension + ".png"
let imageFileURL = DatabaseManager.saveStatesDirectoryURLForGame(self.game).URLByAppendingPathComponent(imageFilename) let imageFileURL = try! DatabaseManager.saveStatesDirectoryURLForGame(self.game).appendingPathComponent(imageFilename)
return imageFileURL return imageFileURL
} }
} }
@ -67,15 +67,15 @@ extension SaveState
{ {
@NSManaged private var primitiveFilename: String @NSManaged private var primitiveFilename: String
@NSManaged private var primitiveIdentifier: String @NSManaged private var primitiveIdentifier: String
@NSManaged private var primitiveCreationDate: NSDate @NSManaged private var primitiveCreationDate: Date
@NSManaged private var primitiveModifiedDate: NSDate @NSManaged private var primitiveModifiedDate: Date
override func awakeFromInsert() override func awakeFromInsert()
{ {
super.awakeFromInsert() super.awakeFromInsert()
let identifier = NSUUID().UUIDString let identifier = UUID().uuidString
let date = NSDate() let date = Date()
self.primitiveIdentifier = identifier self.primitiveIdentifier = identifier
self.primitiveFilename = identifier self.primitiveFilename = identifier

View File

@ -15,31 +15,31 @@ extension NSManagedObject
return NSStringFromClass(self) return NSStringFromClass(self)
} }
class func insertIntoManagedObjectContext(managedObjectContext: NSManagedObjectContext) -> Self class func insertIntoManagedObjectContext(_ managedObjectContext: NSManagedObjectContext) -> Self
{ {
return self.insertIntoManagedObjectContext(managedObjectContext, type: self) return self.insertIntoManagedObjectContext(managedObjectContext, type: self)
} }
private class func insertIntoManagedObjectContext<T>(managedObjectContext: NSManagedObjectContext, type: T.Type) -> T private class func insertIntoManagedObjectContext<T>(_ managedObjectContext: NSManagedObjectContext, type: T.Type) -> T
{ {
let object = NSEntityDescription.insertNewObjectForEntityForName(self.entityName, inManagedObjectContext: managedObjectContext) as! T let object = NSEntityDescription.insertNewObject(forEntityName: self.entityName, into: managedObjectContext) as! T
return object return object
} }
// MARK: - Fetches - // MARK: - Fetches -
class func fetchRequest() -> NSFetchRequest class func fetchRequest() -> NSFetchRequest<AnyObject>
{ {
let fetchRequest = NSFetchRequest(entityName: self.entityName) let fetchRequest = NSFetchRequest(entityName: self.entityName)
return fetchRequest return fetchRequest
} }
class func instancesInManagedObjectContext<T: NSManagedObject>(managedObjectContext: NSManagedObjectContext, type: T.Type) -> [T] class func instancesInManagedObjectContext<T: NSManagedObject>(_ managedObjectContext: NSManagedObjectContext, type: T.Type) -> [T]
{ {
return self.instancesWithPredicate(nil, inManagedObjectContext: managedObjectContext, type: type) return self.instancesWithPredicate(nil, inManagedObjectContext: managedObjectContext, type: type)
} }
class func instancesWithPredicate<T: NSManagedObject>(predicate: NSPredicate?, inManagedObjectContext managedObjectContext: NSManagedObjectContext, type: T.Type) -> [T] class func instancesWithPredicate<T: NSManagedObject>(_ predicate: Predicate?, inManagedObjectContext managedObjectContext: NSManagedObjectContext, type: T.Type) -> [T]
{ {
let fetchRequest = self.fetchRequest() let fetchRequest = self.fetchRequest()
fetchRequest.predicate = predicate fetchRequest.predicate = predicate
@ -48,7 +48,7 @@ extension NSManagedObject
do do
{ {
results = try managedObjectContext.executeFetchRequest(fetchRequest) as! [T] results = try managedObjectContext.fetch(fetchRequest) as! [T]
} }
catch let error as NSError catch let error as NSError
{ {

View File

@ -13,15 +13,15 @@ import DeltaCore
protocol GamePickerControllerDelegate protocol GamePickerControllerDelegate
{ {
func gamePickerController(gamePickerController: GamePickerController, didImportGames games: [Game]) func gamePickerController(_ gamePickerController: GamePickerController, didImportGames games: [Game])
/** Optional **/ /** Optional **/
func gamePickerControllerDidCancel(gamePickerController: GamePickerController) func gamePickerControllerDidCancel(_ gamePickerController: GamePickerController)
} }
extension GamePickerControllerDelegate extension GamePickerControllerDelegate
{ {
func gamePickerControllerDidCancel(gamePickerController: GamePickerController) func gamePickerControllerDidCancel(_ gamePickerController: GamePickerController)
{ {
// Empty Implementation // Empty Implementation
} }
@ -33,34 +33,34 @@ class GamePickerController: NSObject
private weak var presentingViewController: UIViewController? private weak var presentingViewController: UIViewController?
private func presentGamePickerControllerFromPresentingViewController(presentingViewController: UIViewController, animated: Bool, completion: (Void -> Void)?) private func presentGamePickerControllerFromPresentingViewController(_ presentingViewController: UIViewController, animated: Bool, completion: ((Void) -> Void)?)
{ {
self.presentingViewController = presentingViewController self.presentingViewController = presentingViewController
#if os(iOS) #if os(iOS)
let documentMenuController = UIDocumentMenuViewController(documentTypes: Array(Game.supportedTypeIdentifiers()), inMode: .Import) let documentMenuController = UIDocumentMenuViewController(documentTypes: Array(Game.supportedTypeIdentifiers()), in: .import)
documentMenuController.delegate = self documentMenuController.delegate = self
documentMenuController.addOptionWithTitle(NSLocalizedString("iTunes", comment: ""), image: nil, order: .First) { self.importFromiTunes(nil) } documentMenuController.addOption(withTitle: NSLocalizedString("iTunes", comment: ""), image: nil, order: .first) { self.importFromiTunes(nil) }
self.presentingViewController?.presentViewController(documentMenuController, animated: true, completion: nil) self.presentingViewController?.present(documentMenuController, animated: true, completion: nil)
#else #else
self.importFromiTunes(completion) self.importFromiTunes(completion)
#endif #endif
} }
private func importFromiTunes(completion: (Void -> Void)?) private func importFromiTunes(_ completion: ((Void) -> Void)?)
{ {
let alertController = UIAlertController(title: NSLocalizedString("Import from iTunes?", comment: ""), message: NSLocalizedString("Delta will import the games copied over via iTunes.", comment: ""), preferredStyle: .Alert) let alertController = UIAlertController(title: NSLocalizedString("Import from iTunes?", comment: ""), message: NSLocalizedString("Delta will import the games copied over via iTunes.", comment: ""), preferredStyle: .alert)
let importAction = UIAlertAction(title: NSLocalizedString("Import", comment: ""), style: .Default) { action in let importAction = UIAlertAction(title: NSLocalizedString("Import", comment: ""), style: .default) { action in
let documentsDirectoryURL = DatabaseManager.databaseDirectoryURL.URLByDeletingLastPathComponent let documentsDirectoryURL = try! DatabaseManager.databaseDirectoryURL.deletingLastPathComponent
do do
{ {
let contents = try NSFileManager.defaultManager().contentsOfDirectoryAtURL(documentsDirectoryURL!, includingPropertiesForKeys: nil, options: .SkipsHiddenFiles) let contents = try FileManager.default.contentsOfDirectory(at: documentsDirectoryURL!, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
let managedObjectContext = DatabaseManager.sharedManager.backgroundManagedObjectContext() let managedObjectContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
managedObjectContext.performBlock() { managedObjectContext.perform() {
let gameURLs = contents.filter({ GameCollection.gameSystemCollectionForPathExtension($0.pathExtension, inManagedObjectContext: managedObjectContext).identifier != kUTTypeDeltaGame as String }) let gameURLs = contents.filter({ GameCollection.gameSystemCollectionForPathExtension($0.pathExtension, inManagedObjectContext: managedObjectContext).identifier != kUTTypeDeltaGame as String })
self.importGamesAtURLs(gameURLs) self.importGamesAtURLs(gameURLs)
} }
@ -76,22 +76,22 @@ class GamePickerController: NSObject
} }
alertController.addAction(importAction) alertController.addAction(importAction)
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel) { action in let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel) { action in
self.delegate?.gamePickerControllerDidCancel(self) self.delegate?.gamePickerControllerDidCancel(self)
self.presentingViewController?.gamePickerController = nil self.presentingViewController?.gamePickerController = nil
} }
alertController.addAction(cancelAction) alertController.addAction(cancelAction)
self.presentingViewController?.presentViewController(alertController, animated: true, completion: completion) self.presentingViewController?.present(alertController, animated: true, completion: completion)
} }
private func importGamesAtURLs(URLs: [NSURL]) private func importGamesAtURLs(_ URLs: [URL])
{ {
DatabaseManager.sharedManager.importGamesAtURLs(URLs) { identifiers in DatabaseManager.sharedManager.importGamesAtURLs(URLs) { identifiers in
DatabaseManager.sharedManager.managedObjectContext.performBlock() { DatabaseManager.sharedManager.managedObjectContext.perform() {
let predicate = NSPredicate(format: "%K IN (%@)", Game.Attributes.identifier.rawValue, identifiers) let predicate = Predicate(format: "%K IN (%@)", Game.Attributes.identifier.rawValue, identifiers)
let games = Game.instancesWithPredicate(predicate, inManagedObjectContext: DatabaseManager.sharedManager.managedObjectContext, type: Game.self) let games = Game.instancesWithPredicate(predicate, inManagedObjectContext: DatabaseManager.sharedManager.managedObjectContext, type: Game.self)
self.delegate?.gamePickerController(self, didImportGames: games) self.delegate?.gamePickerController(self, didImportGames: games)
@ -107,15 +107,15 @@ class GamePickerController: NSObject
extension GamePickerController: UIDocumentMenuDelegate extension GamePickerController: UIDocumentMenuDelegate
{ {
func documentMenu(documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController)
{ {
documentPicker.delegate = self documentPicker.delegate = self
self.presentingViewController?.presentViewController(documentPicker, animated: true, completion: nil) self.presentingViewController?.present(documentPicker, animated: true, completion: nil)
self.presentingViewController?.gamePickerController = nil self.presentingViewController?.gamePickerController = nil
} }
func documentMenuWasCancelled(documentMenu: UIDocumentMenuViewController) func documentMenuWasCancelled(_ documentMenu: UIDocumentMenuViewController)
{ {
self.delegate?.gamePickerControllerDidCancel(self) self.delegate?.gamePickerControllerDidCancel(self)
@ -126,14 +126,14 @@ class GamePickerController: NSObject
extension GamePickerController: UIDocumentPickerDelegate extension GamePickerController: UIDocumentPickerDelegate
{ {
func documentPicker(controller: UIDocumentPickerViewController, didPickDocumentAtURL url: NSURL) func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL)
{ {
self.importGamesAtURLs([url]) self.importGamesAtURLs([url])
self.presentingViewController?.gamePickerController = nil self.presentingViewController?.gamePickerController = nil
} }
func documentPickerWasCancelled(controller: UIDocumentPickerViewController) func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController)
{ {
self.delegate?.gamePickerControllerDidCancel(self) self.delegate?.gamePickerControllerDidCancel(self)
@ -159,7 +159,7 @@ extension UIViewController
} }
} }
func presentGamePickerController(gamePickerController: GamePickerController, animated: Bool, completion: (Void -> Void)?) func presentGamePickerController(_ gamePickerController: GamePickerController, animated: Bool, completion: ((Void) -> Void)?)
{ {
self.gamePickerController = gamePickerController self.gamePickerController = gamePickerController

View File

@ -439,6 +439,7 @@
BFFA71D61AAC406100EE9DD1 = { BFFA71D61AAC406100EE9DD1 = {
CreatedOnToolsVersion = 6.3; CreatedOnToolsVersion = 6.3;
DevelopmentTeam = 6XVY5G3U44; DevelopmentTeam = 6XVY5G3U44;
LastSwiftMigration = 0800;
SystemCapabilities = { SystemCapabilities = {
com.apple.iCloud = { com.apple.iCloud = {
enabled = 1; enabled = 1;
@ -706,6 +707,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
SWIFT_OBJC_BRIDGING_HEADER = "Delta/Supporting Files/Delta-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Delta/Supporting Files/Delta-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
}; };
name = Debug; name = Debug;
}; };
@ -720,6 +722,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 10.0; IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
SWIFT_OBJC_BRIDGING_HEADER = "Delta/Supporting Files/Delta-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Delta/Supporting Files/Delta-Bridging-Header.h";
SWIFT_VERSION = 3.0;
}; };
name = Release; name = Release;
}; };

View File

@ -15,19 +15,19 @@ class AppDelegate: UIResponder, UIApplicationDelegate
{ {
var window: UIWindow? var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{ {
self.window?.tintColor = UIColor.deltaPurpleColor() self.window?.tintColor = UIColor.deltaPurpleColor()
// Database // Database
let semaphore = dispatch_semaphore_create(0) let semaphore = DispatchSemaphore(value: 0)
DatabaseManager.sharedManager.startWithCompletion { performingMigration in DatabaseManager.sharedManager.startWithCompletion { performingMigration in
dispatch_semaphore_signal(semaphore) semaphore.signal()
} }
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) semaphore.wait(timeout: DispatchTime.distantFuture)
// Controllers // Controllers
ExternalControllerManager.sharedManager.startMonitoringExternalControllers() ExternalControllerManager.sharedManager.startMonitoringExternalControllers()
@ -35,29 +35,29 @@ class AppDelegate: UIResponder, UIApplicationDelegate
return true return true
} }
func applicationWillResignActive(application: UIApplication) func applicationWillResignActive(_ application: UIApplication)
{ {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
} }
func applicationDidEnterBackground(application: UIApplication) func applicationDidEnterBackground(_ application: UIApplication)
{ {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
} }
func applicationWillEnterForeground(application: UIApplication) func applicationWillEnterForeground(_ application: UIApplication)
{ {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
} }
func applicationDidBecomeActive(application: UIApplication) func applicationDidBecomeActive(_ application: UIApplication)
{ {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
} }
func applicationWillTerminate(application: UIApplication) func applicationWillTerminate(_ application: UIApplication)
{ {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
} }

View File

@ -14,7 +14,7 @@ import Roxas
// Temporary wrapper around dispatch_semaphore_t until Swift 3 + modernized libdispatch // Temporary wrapper around dispatch_semaphore_t until Swift 3 + modernized libdispatch
private struct DispatchSemaphore: Hashable private struct DispatchSemaphore: Hashable
{ {
let semaphore: dispatch_semaphore_t let semaphore: Dispatch.DispatchSemaphore
var hashValue: Int { var hashValue: Int {
return semaphore.hash return semaphore.hash
@ -22,7 +22,7 @@ private struct DispatchSemaphore: Hashable
init(value: Int) init(value: Int)
{ {
self.semaphore = dispatch_semaphore_create(value) self.semaphore = DispatchSemaphore(value: value)
} }
} }
@ -66,7 +66,7 @@ class EmulationViewController: UIViewController
// Annoying iOS gotcha: if the previewingContext(_:viewControllerForLocation:) callback takes too long, the peek/preview starts, but fails to actually present the view controller // Annoying iOS gotcha: if the previewingContext(_:viewControllerForLocation:) callback takes too long, the peek/preview starts, but fails to actually present the view controller
// To workaround, we have this closure to defer work for Peeking/Popping until the view controller appears // To workaround, we have this closure to defer work for Peeking/Popping until the view controller appears
// Hacky, but works // Hacky, but works
var deferredPreparationHandler: (Void -> Void)? var deferredPreparationHandler: ((Void) -> Void)?
//MARK: - Private Properties //MARK: - Private Properties
private var pauseViewController: PauseViewController? private var pauseViewController: PauseViewController?
@ -77,7 +77,7 @@ class EmulationViewController: UIViewController
private var updateSemaphores = Set<DispatchSemaphore>() private var updateSemaphores = Set<DispatchSemaphore>()
private var sustainedInputs = [ObjectIdentifier: [InputType]]() private var sustainedInputs = [ObjectIdentifier: [InputType]]()
private var reactivateSustainInputsQueue: NSOperationQueue private var reactivateSustainInputsQueue: OperationQueue
private var choosingSustainedButtons = false private var choosingSustainedButtons = false
@IBOutlet private var controllerView: ControllerView! @IBOutlet private var controllerView: ControllerView!
@ -92,16 +92,16 @@ class EmulationViewController: UIViewController
/** Initializers **/ /** Initializers **/
required init?(coder aDecoder: NSCoder) required init?(coder aDecoder: NSCoder)
{ {
self.reactivateSustainInputsQueue = NSOperationQueue() self.reactivateSustainInputsQueue = OperationQueue()
self.reactivateSustainInputsQueue.maxConcurrentOperationCount = 1 self.reactivateSustainInputsQueue.maxConcurrentOperationCount = 1
super.init(coder: aDecoder) super.init(coder: aDecoder)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(EmulationViewController.updateControllers), name: ExternalControllerDidConnectNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(EmulationViewController.updateControllers), name: ExternalControllerDidConnectNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(EmulationViewController.updateControllers), name: ExternalControllerDidDisconnectNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(EmulationViewController.updateControllers), name: ExternalControllerDidDisconnectNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(EmulationViewController.willResignActive(_:)), name: UIApplicationWillResignActiveNotification, object: UIApplication.sharedApplication()) NotificationCenter.default.addObserver(self, selector: #selector(EmulationViewController.willResignActive(_:)), name: NSNotification.Name.UIApplicationWillResignActive, object: UIApplication.shared())
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(EmulationViewController.didBecomeActive(_:)), name: UIApplicationDidBecomeActiveNotification, object: UIApplication.sharedApplication()) NotificationCenter.default.addObserver(self, selector: #selector(EmulationViewController.didBecomeActive(_:)), name: NSNotification.Name.UIApplicationDidBecomeActive, object: UIApplication.shared())
} }
deinit deinit
@ -123,7 +123,7 @@ class EmulationViewController: UIViewController
// (such as when peeking and popping) // (such as when peeking and popping)
self.controllerViewHeightConstraint.constant = 0 self.controllerViewHeightConstraint.constant = 0
self.gameView.backgroundColor = UIColor.clearColor() self.gameView.backgroundColor = UIColor.clear()
self.emulatorCore.addGameView(self.gameView) self.emulatorCore.addGameView(self.gameView)
self.backgroundView.textLabel.text = NSLocalizedString("Select Buttons to Sustain", comment: "") self.backgroundView.textLabel.text = NSLocalizedString("Select Buttons to Sustain", comment: "")
@ -137,7 +137,7 @@ class EmulationViewController: UIViewController
self.updateControllers() self.updateControllers()
} }
override func viewDidAppear(animated: Bool) override func viewDidAppear(_ animated: Bool)
{ {
super.viewDidAppear(animated) super.viewDidAppear(animated)
@ -147,12 +147,12 @@ class EmulationViewController: UIViewController
// Yes, order DOES matter here, in order to prevent audio from being slightly delayed after peeking with 3D Touch (ugh so tired of that issue) // Yes, order DOES matter here, in order to prevent audio from being slightly delayed after peeking with 3D Touch (ugh so tired of that issue)
switch self.emulatorCore.state switch self.emulatorCore.state
{ {
case .Stopped: case .stopped:
self.emulatorCore.startEmulation() self.emulatorCore.startEmulation()
self.updateCheats() self.updateCheats()
case .Running: break case .running: break
case .Paused: case .paused:
self.updateCheats() self.updateCheats()
self.resumeEmulation() self.resumeEmulation()
} }
@ -177,7 +177,7 @@ class EmulationViewController: UIViewController
self.controllerViewHeightConstraint.constant = 0 self.controllerViewHeightConstraint.constant = 0
} }
self.controllerView.hidden = self.isPreviewing self.controllerView.isHidden = self.isPreviewing
} }
override func prefersStatusBarHidden() -> Bool override func prefersStatusBarHidden() -> Bool
@ -186,15 +186,15 @@ class EmulationViewController: UIViewController
} }
/// <UIContentContainer> /// <UIContentContainer>
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
{ {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) super.viewWillTransition(to: size, with: coordinator)
self.controllerView.beginAnimatingUpdateControllerSkin() self.controllerView.beginAnimatingUpdateControllerSkin()
coordinator.animateAlongsideTransition({ _ in coordinator.animate(alongsideTransition: { _ in
if self.emulatorCore.state == .Paused if self.emulatorCore.state == .paused
{ {
// We need to manually "refresh" the game screen, otherwise the system tries to cache the rendered image, but skews it incorrectly when rotating b/c of UIVisualEffectView // We need to manually "refresh" the game screen, otherwise the system tries to cache the rendered image, but skews it incorrectly when rotating b/c of UIVisualEffectView
self.gameView.inputImage = self.gameView.outputImage self.gameView.inputImage = self.gameView.outputImage
@ -208,7 +208,7 @@ class EmulationViewController: UIViewController
// MARK: - Navigation - // MARK: - Navigation -
// In a storyboard-based application, you will often want to do a little preparation before navigation // In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
{ {
self.pauseEmulation() self.pauseEmulation()
@ -226,11 +226,11 @@ class EmulationViewController: UIViewController
// As a dirty workaround, we just use a weak reference, and force unwrap it if needed // As a dirty workaround, we just use a weak reference, and force unwrap it if needed
let saveStateItem = PauseItem(image: UIImage(named: "SaveSaveState")!, text: NSLocalizedString("Save State", comment: ""), action: { [unowned self] _ in let saveStateItem = PauseItem(image: UIImage(named: "SaveSaveState")!, text: NSLocalizedString("Save State", comment: ""), action: { [unowned self] _ in
pauseViewController.presentSaveStateViewControllerWithMode(.Saving, delegate: self) pauseViewController.presentSaveStateViewControllerWithMode(.saving, delegate: self)
}) })
let loadStateItem = PauseItem(image: UIImage(named: "LoadSaveState")!, text: NSLocalizedString("Load State", comment: ""), action: { [unowned self] _ in let loadStateItem = PauseItem(image: UIImage(named: "LoadSaveState")!, text: NSLocalizedString("Load State", comment: ""), action: { [unowned self] _ in
pauseViewController.presentSaveStateViewControllerWithMode(.Loading, delegate: self) pauseViewController.presentSaveStateViewControllerWithMode(.loading, delegate: self)
}) })
let cheatCodesItem = PauseItem(image: UIImage(named: "SmallPause")!, text: NSLocalizedString("Cheat Codes", comment: ""), action: { [unowned self] _ in let cheatCodesItem = PauseItem(image: UIImage(named: "SmallPause")!, text: NSLocalizedString("Cheat Codes", comment: ""), action: { [unowned self] _ in
@ -260,7 +260,7 @@ class EmulationViewController: UIViewController
} }
} }
@IBAction func unwindFromPauseViewController(segue: UIStoryboardSegue) @IBAction func unwindFromPauseViewController(_ segue: UIStoryboardSegue)
{ {
self.pauseViewController = nil self.pauseViewController = nil
self.pausingGameController = nil self.pausingGameController = nil
@ -271,7 +271,7 @@ class EmulationViewController: UIViewController
self.emulatorCore.audioManager.enabled = false self.emulatorCore.audioManager.enabled = false
// Re-enable after delay // Re-enable after delay
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { DispatchQueue.main.after(when: DispatchTime.now() + Double(Int64(0.1 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) {
self.emulatorCore.audioManager.enabled = true self.emulatorCore.audioManager.enabled = true
} }
} }
@ -288,10 +288,10 @@ class EmulationViewController: UIViewController
let presentingViewController = self.presentingViewController let presentingViewController = self.presentingViewController
let launchGameAction = UIPreviewAction(title: NSLocalizedString("Launch \(self.game.name)", comment: ""), style: .Default) { (action, viewController) in let launchGameAction = UIPreviewAction(title: NSLocalizedString("Launch \(self.game.name)", comment: ""), style: .default) { (action, viewController) in
// Delaying until next run loop prevents self from being dismissed immediately // Delaying until next run loop prevents self from being dismissed immediately
dispatch_async(dispatch_get_main_queue()) { DispatchQueue.main.async {
presentingViewController?.presentViewController(viewController, animated: true, completion: nil) presentingViewController?.present(viewController, animated: true, completion: nil)
} }
} }
return [launchGameAction] return [launchGameAction]
@ -302,9 +302,9 @@ class EmulationViewController: UIViewController
/// Emulation /// Emulation
private extension EmulationViewController private extension EmulationViewController
{ {
func pause(sender sender: AnyObject?) func pause(sender: AnyObject?)
{ {
self.performSegueWithIdentifier("pauseSegue", sender: sender) self.performSegue(withIdentifier: "pauseSegue", sender: sender)
} }
func pauseEmulation() -> Bool func pauseEmulation() -> Bool
@ -319,11 +319,11 @@ private extension EmulationViewController
return self.emulatorCore.resumeEmulation() return self.emulatorCore.resumeEmulation()
} }
func emulatorCoreDidUpdate(emulatorCore: EmulatorCore) func emulatorCoreDidUpdate(_ emulatorCore: EmulatorCore)
{ {
for semaphore in self.updateSemaphores for semaphore in self.updateSemaphores
{ {
dispatch_semaphore_signal(semaphore.semaphore) semaphore.semaphore.signal()
} }
} }
} }
@ -345,7 +345,7 @@ private extension EmulationViewController
controllers.append(self.controllerView) controllers.append(self.controllerView)
// We need to map each item as a GameControllerProtocol due to a Swift bug // We need to map each item as a GameControllerProtocol due to a Swift bug
controllers.appendContentsOf(ExternalControllerManager.sharedManager.connectedControllers.map { $0 as GameControllerProtocol }) controllers.append(contentsOf: ExternalControllerManager.sharedManager.connectedControllers.map { $0 as GameControllerProtocol })
for controller in controllers for controller in controllers
{ {
@ -370,17 +370,17 @@ private extension EmulationViewController
func showSustainButtonView() func showSustainButtonView()
{ {
self.choosingSustainedButtons = true self.choosingSustainedButtons = true
self.sustainButtonContentView.hidden = false self.sustainButtonContentView.isHidden = false
} }
func hideSustainButtonView() func hideSustainButtonView()
{ {
self.choosingSustainedButtons = false self.choosingSustainedButtons = false
UIView.animateWithDuration(0.4, animations: { UIView.animate(withDuration: 0.4, animations: {
self.sustainButtonContentView.alpha = 0.0 self.sustainButtonContentView.alpha = 0.0
}) { (finished) in }) { (finished) in
self.sustainButtonContentView.hidden = true self.sustainButtonContentView.isHidden = true
self.sustainButtonContentView.alpha = 1.0 self.sustainButtonContentView.alpha = 1.0
} }
} }
@ -405,7 +405,7 @@ private extension EmulationViewController
self.sustainedInputs[ObjectIdentifier(gameController)] = [] self.sustainedInputs[ObjectIdentifier(gameController)] = []
} }
func addSustainedInput(input: InputType, gameController: GameControllerProtocol) func addSustainedInput(_ input: InputType, gameController: GameControllerProtocol)
{ {
var inputs = self.sustainedInputs[ObjectIdentifier(gameController)] ?? [] var inputs = self.sustainedInputs[ObjectIdentifier(gameController)] ?? []
@ -424,10 +424,10 @@ private extension EmulationViewController
receivers.forEach { gameController.addReceiver($0) } receivers.forEach { gameController.addReceiver($0) }
} }
func reactivateSustainedInput(input: InputType, gameController: GameControllerProtocol) func reactivateSustainedInput(_ input: InputType, gameController: GameControllerProtocol)
{ {
// These MUST be performed serially, or else Bad Things Happen if multiple inputs are reactivated at once // These MUST be performed serially, or else Bad Things Happen if multiple inputs are reactivated at once
self.reactivateSustainInputsQueue.addOperationWithBlock { self.reactivateSustainInputsQueue.addOperation {
// The manual activations/deactivations here are hidden implementation details, so we won't notify ourselves about them // The manual activations/deactivations here are hidden implementation details, so we won't notify ourselves about them
gameController.removeReceiver(self) gameController.removeReceiver(self)
@ -435,8 +435,8 @@ private extension EmulationViewController
// Must deactivate first so core recognizes a secondary activation // Must deactivate first so core recognizes a secondary activation
gameController.deactivate(input) gameController.deactivate(input)
let dispatchQueue = dispatch_queue_create("com.rileytestut.Delta.sustainButtonsQueue", DISPATCH_QUEUE_SERIAL) let dispatchQueue = DispatchQueue(label: "com.rileytestut.Delta.sustainButtonsQueue", attributes: DispatchQueueAttributes.serial)
dispatch_async(dispatchQueue) { dispatchQueue.async {
let semaphore = DispatchSemaphore(value: 0) let semaphore = DispatchSemaphore(value: 0)
self.updateSemaphores.insert(semaphore) self.updateSemaphores.insert(semaphore)
@ -444,11 +444,11 @@ private extension EmulationViewController
// To ensure the emulator core recognizes us activating the input again, we need to wait at least two frames // To ensure the emulator core recognizes us activating the input again, we need to wait at least two frames
// Unfortunately we cannot init DispatchSemaphore with value less than 0 // Unfortunately we cannot init DispatchSemaphore with value less than 0
// To compensate, we simply wait twice; once the first wait returns, we wait again // To compensate, we simply wait twice; once the first wait returns, we wait again
dispatch_semaphore_wait(semaphore.semaphore, DISPATCH_TIME_FOREVER) semaphore.semaphore.wait(timeout: DispatchTime.distantFuture)
dispatch_semaphore_wait(semaphore.semaphore, DISPATCH_TIME_FOREVER) semaphore.semaphore.wait(timeout: DispatchTime.distantFuture)
// These MUST be performed serially, or else Bad Things Happen if multiple inputs are reactivated at once // These MUST be performed serially, or else Bad Things Happen if multiple inputs are reactivated at once
self.reactivateSustainInputsQueue.addOperationWithBlock { self.reactivateSustainInputsQueue.addOperation {
self.updateSemaphores.remove(semaphore) self.updateSemaphores.remove(semaphore)
@ -481,12 +481,12 @@ private extension EmulationViewController
/// Save States /// Save States
extension EmulationViewController: SaveStatesViewControllerDelegate extension EmulationViewController: SaveStatesViewControllerDelegate
{ {
func saveStatesViewControllerActiveEmulatorCore(saveStatesViewController: SaveStatesViewController) -> EmulatorCore func saveStatesViewControllerActiveEmulatorCore(_ saveStatesViewController: SaveStatesViewController) -> EmulatorCore
{ {
return self.emulatorCore return self.emulatorCore
} }
func saveStatesViewController(saveStatesViewController: SaveStatesViewController, updateSaveState saveState: SaveState) func saveStatesViewController(_ saveStatesViewController: SaveStatesViewController, updateSaveState saveState: SaveState)
{ {
guard let filepath = saveState.fileURL.path else { return } guard let filepath = saveState.fileURL.path else { return }
@ -495,13 +495,13 @@ extension EmulationViewController: SaveStatesViewControllerDelegate
self.emulatorCore.saveSaveState { temporarySaveState in self.emulatorCore.saveSaveState { temporarySaveState in
do do
{ {
if NSFileManager.defaultManager().fileExistsAtPath(filepath) if FileManager.default.fileExists(atPath: filepath)
{ {
try NSFileManager.defaultManager().replaceItemAtURL(saveState.fileURL, withItemAtURL: temporarySaveState.fileURL, backupItemName: nil, options: [], resultingItemURL: nil) try FileManager.default.replaceItem(at: saveState.fileURL, withItemAt: temporarySaveState.fileURL, backupItemName: nil, options: [], resultingItemURL: nil)
} }
else else
{ {
try NSFileManager.defaultManager().moveItemAtURL(temporarySaveState.fileURL, toURL: saveState.fileURL) try FileManager.default.moveItem(at: temporarySaveState.fileURL, to: saveState.fileURL)
updatingExistingSaveState = false updatingExistingSaveState = false
} }
@ -514,13 +514,13 @@ extension EmulationViewController: SaveStatesViewControllerDelegate
if let outputImage = self.gameView.outputImage if let outputImage = self.gameView.outputImage
{ {
let quartzImage = self.context.createCGImage(outputImage, fromRect: outputImage.extent) let quartzImage = self.context.createCGImage(outputImage, from: outputImage.extent)
let image = UIImage(CGImage: quartzImage) let image = UIImage(cgImage: quartzImage)
UIImagePNGRepresentation(image)?.writeToURL(saveState.imageFileURL, atomically: true) try? UIImagePNGRepresentation(image)?.write(to: saveState.imageFileURL, options: [.dataWritingAtomic])
} }
saveState.modifiedDate = NSDate() saveState.modifiedDate = Date()
// Dismiss if updating an existing save state. // Dismiss if updating an existing save state.
// If creating a new one, don't dismiss. // If creating a new one, don't dismiss.
@ -530,7 +530,7 @@ extension EmulationViewController: SaveStatesViewControllerDelegate
} }
} }
func saveStatesViewController(saveStatesViewController: SaveStatesViewController, loadSaveState saveState: SaveStateType) func saveStatesViewController(_ saveStatesViewController: SaveStatesViewController, loadSaveState saveState: SaveStateType)
{ {
do do
{ {
@ -555,17 +555,17 @@ extension EmulationViewController: SaveStatesViewControllerDelegate
/// Cheats /// Cheats
extension EmulationViewController: CheatsViewControllerDelegate extension EmulationViewController: CheatsViewControllerDelegate
{ {
func cheatsViewControllerActiveEmulatorCore(saveStatesViewController: CheatsViewController) -> EmulatorCore func cheatsViewControllerActiveEmulatorCore(_ saveStatesViewController: CheatsViewController) -> EmulatorCore
{ {
return self.emulatorCore return self.emulatorCore
} }
func cheatsViewController(cheatsViewController: CheatsViewController, didActivateCheat cheat: Cheat) throws func cheatsViewController(_ cheatsViewController: CheatsViewController, didActivateCheat cheat: Cheat) throws
{ {
try self.emulatorCore.activateCheat(cheat) try self.emulatorCore.activateCheat(cheat)
} }
func cheatsViewController(cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat) func cheatsViewController(_ cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat)
{ {
self.emulatorCore.deactivateCheat(cheat) self.emulatorCore.deactivateCheat(cheat)
} }
@ -573,9 +573,9 @@ extension EmulationViewController: CheatsViewControllerDelegate
private func updateCheats() private func updateCheats()
{ {
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext() let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlockAndWait { backgroundContext.performAndWait {
let running = (self.emulatorCore.state == .Running) let running = (self.emulatorCore.state == .running)
if running if running
{ {
@ -583,7 +583,7 @@ extension EmulationViewController: CheatsViewControllerDelegate
self.pauseEmulation() self.pauseEmulation()
} }
let predicate = NSPredicate(format: "%K == %@", Cheat.Attributes.game.rawValue, self.emulatorCore.game as! Game) let predicate = Predicate(format: "%K == %@", Cheat.Attributes.game.rawValue, self.emulatorCore.game as! Game)
let cheats = Cheat.instancesWithPredicate(predicate, inManagedObjectContext: backgroundContext, type: Cheat.self) let cheats = Cheat.instancesWithPredicate(predicate, inManagedObjectContext: backgroundContext, type: Cheat.self)
for cheat in cheats for cheat in cheats
@ -623,12 +623,12 @@ extension EmulationViewController: CheatsViewControllerDelegate
//MARK: - App Lifecycle - //MARK: - App Lifecycle -
private extension EmulationViewController private extension EmulationViewController
{ {
@objc func willResignActive(notification: NSNotification) @objc func willResignActive(_ notification: Notification)
{ {
self.pauseEmulation() self.pauseEmulation()
} }
@objc func didBecomeActive(notification: NSNotification) @objc func didBecomeActive(_ notification: Notification)
{ {
self.resumeEmulation() self.resumeEmulation()
} }
@ -638,18 +638,18 @@ private extension EmulationViewController
/// <GameControllerReceiver> /// <GameControllerReceiver>
extension EmulationViewController: GameControllerReceiverProtocol extension EmulationViewController: GameControllerReceiverProtocol
{ {
func gameController(gameController: GameControllerProtocol, didActivateInput input: InputType) func gameController(_ gameController: GameControllerProtocol, didActivateInput input: InputType)
{ {
if gameController is ControllerView && UIDevice.currentDevice().supportsVibration if gameController is ControllerView && UIDevice.current().isVibrationSupported
{ {
UIDevice.currentDevice().vibrate() UIDevice.current().vibrate()
} }
if let input = input as? ControllerInput if let input = input as? ControllerInput
{ {
switch input switch input
{ {
case ControllerInput.Menu: case ControllerInput.menu:
if self.choosingSustainedButtons { self.hideSustainButtonView() } if self.choosingSustainedButtons { self.hideSustainButtonView() }
self.pause(sender: gameController) self.pause(sender: gameController)
@ -667,7 +667,7 @@ extension EmulationViewController: GameControllerReceiverProtocol
if let sustainedInputs = self.sustainedInputs[ObjectIdentifier(gameController)] where sustainedInputs.contains({ $0.isEqual(input) }) if let sustainedInputs = self.sustainedInputs[ObjectIdentifier(gameController)] where sustainedInputs.contains({ $0.isEqual(input) })
{ {
// Perform on next run loop // Perform on next run loop
dispatch_async(dispatch_get_main_queue()) { DispatchQueue.main.async {
self.reactivateSustainedInput(input, gameController: gameController) self.reactivateSustainedInput(input, gameController: gameController)
} }
@ -675,7 +675,7 @@ extension EmulationViewController: GameControllerReceiverProtocol
} }
} }
func gameController(gameController: GameControllerProtocol, didDeactivateInput input: InputType) func gameController(_ gameController: GameControllerProtocol, didDeactivateInput input: InputType)
{ {
guard let input = input as? ControllerInput else { return } guard let input = input as? ControllerInput else { return }

View File

@ -18,8 +18,8 @@ internal extension UILabel
context.minimumScaleFactor = self.minimumScaleFactor context.minimumScaleFactor = self.minimumScaleFactor
// Using self.attributedString returns incorrect calculations, so we create our own attributed string // Using self.attributedString returns incorrect calculations, so we create our own attributed string
let attributedString = NSAttributedString(string: text, attributes: [NSFontAttributeName: self.font]) let attributedString = AttributedString(string: text, attributes: [NSFontAttributeName: self.font])
attributedString.boundingRectWithSize(self.bounds.size, options: [.UsesLineFragmentOrigin, .UsesFontLeading], context: context) attributedString.boundingRect(with: self.bounds.size, options: [.usesLineFragmentOrigin, .usesFontLeading], context: context)
let scaleFactor = context.actualScaleFactor let scaleFactor = context.actualScaleFactor
return scaleFactor return scaleFactor

View File

@ -13,6 +13,6 @@ extension UIViewController
var isPreviewing: Bool var isPreviewing: Bool
{ {
guard let presentationController = self.presentationController else { return false } guard let presentationController = self.presentationController else { return false }
return NSStringFromClass(presentationController.dynamicType).containsString("PreviewPresentation") return NSStringFromClass(presentationController.dynamicType).contains("PreviewPresentation")
} }
} }

View File

@ -46,7 +46,7 @@ class GamesCollectionViewController: UICollectionViewController
} }
} }
override func viewWillAppear(animated: Bool) override func viewWillAppear(_ animated: Bool)
{ {
self.dataSource.update() self.dataSource.update()
@ -62,14 +62,14 @@ class GamesCollectionViewController: UICollectionViewController
// MARK: - Navigation - // MARK: - Navigation -
// In a storyboard-based application, you will often want to do a little preparation before navigation // In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
{ {
self.segueHandler?.prepareForSegue(segue, sender: sender) self.segueHandler?.prepare(for: segue, sender: sender)
} }
// MARK: - Collection View - // MARK: - Collection View -
private func configureCell(cell: GridCollectionViewCell, game: Game) private func configureCell(_ cell: GridCollectionViewCell, game: Game)
{ {
cell.maximumImageSize = CGSize(width: 90, height: 90) cell.maximumImageSize = CGSize(width: 90, height: 90)
cell.textLabel.text = game.name cell.textLabel.text = game.name
@ -79,7 +79,7 @@ class GamesCollectionViewController: UICollectionViewController
extension GamesCollectionViewController: NSFetchedResultsControllerDelegate extension GamesCollectionViewController: NSFetchedResultsControllerDelegate
{ {
func controllerDidChangeContent(controller: NSFetchedResultsController) func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
{ {
self.collectionView?.reloadData() self.collectionView?.reloadData()
} }

View File

@ -19,16 +19,16 @@ class GamesViewController: UIViewController
private var backgroundView: RSTBackgroundView! private var backgroundView: RSTBackgroundView!
private var pageControl: UIPageControl! private var pageControl: UIPageControl!
private let fetchedResultsController: NSFetchedResultsController private let fetchedResultsController: NSFetchedResultsController<AnyObject>
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
fatalError("initWithNibName: not implemented") fatalError("initWithNibName: not implemented")
} }
required init?(coder aDecoder: NSCoder) required init?(coder aDecoder: NSCoder)
{ {
let fetchRequest = GameCollection.fetchRequest() let fetchRequest = GameCollection.fetchRequest()
fetchRequest.sortDescriptors = [NSSortDescriptor(key: GameCollection.Attributes.index.rawValue, ascending: true)] fetchRequest.sortDescriptors = [SortDescriptor(key: GameCollection.Attributes.index.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: nil, cacheName: nil)
@ -44,29 +44,29 @@ class GamesViewController: UIViewController
self.automaticallyAdjustsScrollViewInsets = false self.automaticallyAdjustsScrollViewInsets = false
self.backgroundView = RSTBackgroundView(frame: self.view.bounds) self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
self.backgroundView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] self.backgroundView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.backgroundView.textLabel.text = NSLocalizedString("No Games", comment: "") 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.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.view.insertSubview(self.backgroundView, at: 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 self.pageViewController.view.isHidden = true
self.pageControl = UIPageControl() self.pageControl = UIPageControl()
self.pageControl.translatesAutoresizingMaskIntoConstraints = false self.pageControl.translatesAutoresizingMaskIntoConstraints = false
self.pageControl.hidesForSinglePage = false self.pageControl.hidesForSinglePage = false
self.pageControl.numberOfPages = 3 self.pageControl.numberOfPages = 3
self.pageControl.currentPageIndicatorTintColor = UIColor.purpleColor() self.pageControl.currentPageIndicatorTintColor = UIColor.purple()
self.pageControl.pageIndicatorTintColor = UIColor.lightGrayColor() self.pageControl.pageIndicatorTintColor = UIColor.lightGray()
self.navigationController?.toolbar.addSubview(self.pageControl) self.navigationController?.toolbar.addSubview(self.pageControl)
self.pageControl.centerXAnchor.constraintEqualToAnchor(self.navigationController?.toolbar.centerXAnchor, constant: 0).active = true self.pageControl.centerXAnchor.constraint(equalTo: (self.navigationController?.toolbar.centerXAnchor)!, constant: 0).isActive = true
self.pageControl.centerYAnchor.constraintEqualToAnchor(self.navigationController?.toolbar.centerYAnchor, constant: 0).active = true self.pageControl.centerYAnchor.constraint(equalTo: (self.navigationController?.toolbar.centerYAnchor)!, constant: 0).isActive = true
} }
override func viewWillAppear(animated: Bool) override func viewWillAppear(_ animated: Bool)
{ {
super.viewWillAppear(animated) super.viewWillAppear(animated)
@ -115,14 +115,14 @@ class GamesViewController: UIViewController
// MARK: - Navigation - // MARK: - Navigation -
// In a storyboard-based application, you will often want to do a little preparation before navigation // In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
{ {
guard let sourceViewController = segue.sourceViewController as? GamesCollectionViewController else { return } guard let sourceViewController = segue.sourceViewController as? GamesCollectionViewController else { return }
guard let destinationViewController = segue.destinationViewController as? EmulationViewController else { return } guard let destinationViewController = segue.destinationViewController as? EmulationViewController else { return }
guard let cell = sender as? UICollectionViewCell else { return } guard let cell = sender as? UICollectionViewCell else { return }
let indexPath = sourceViewController.collectionView?.indexPathForCell(cell) let indexPath = sourceViewController.collectionView?.indexPath(for: cell)
let game = sourceViewController.dataSource.fetchedResultsController.objectAtIndexPath(indexPath!) as! Game let game = sourceViewController.dataSource.fetchedResultsController.object(at: indexPath!) as! Game
destinationViewController.game = game destinationViewController.game = game
@ -153,12 +153,12 @@ class GamesViewController: UIViewController
} }
} }
@IBAction func unwindFromSettingsViewController(segue: UIStoryboardSegue) @IBAction func unwindFromSettingsViewController(_ segue: UIStoryboardSegue)
{ {
} }
@IBAction func unwindFromEmulationViewController(segue: UIStoryboardSegue) @IBAction func unwindFromEmulationViewController(_ segue: UIStoryboardSegue)
{ {
} }
@ -166,7 +166,7 @@ class GamesViewController: UIViewController
private extension GamesViewController private extension GamesViewController
{ {
func viewControllerForIndex(index: Int) -> GamesCollectionViewController? func viewControllerForIndex(_ index: Int) -> GamesCollectionViewController?
{ {
guard let pages = self.fetchedResultsController.sections?.first?.numberOfObjects where pages > 0 else { return nil } guard let pages = self.fetchedResultsController.sections?.first?.numberOfObjects where pages > 0 else { return nil }
@ -179,10 +179,10 @@ private extension GamesViewController
safeIndex = pages + safeIndex safeIndex = pages + safeIndex
} }
let indexPath = NSIndexPath(forRow: safeIndex, inSection: 0) let indexPath = IndexPath(row: safeIndex, section: 0)
let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("gamesCollectionViewController") as! GamesCollectionViewController let viewController = self.storyboard?.instantiateViewController(withIdentifier: "gamesCollectionViewController") as! GamesCollectionViewController
viewController.gameCollection = self.fetchedResultsController.objectAtIndexPath(indexPath) as! GameCollection viewController.gameCollection = self.fetchedResultsController.object(at: indexPath) as! GameCollection
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
viewController.segueHandler = self viewController.segueHandler = self
@ -198,7 +198,7 @@ private extension GamesViewController
if let viewController = pageViewController.viewControllers?.first as? GamesCollectionViewController, let gameCollection = viewController.gameCollection if let viewController = pageViewController.viewControllers?.first as? GamesCollectionViewController, let gameCollection = viewController.gameCollection
{ {
if let index = self.fetchedResultsController.fetchedObjects?.indexOf({ $0 as! GameCollection == gameCollection }) if let index = self.fetchedResultsController.fetchedObjects?.index(where: { $0 as! GameCollection == gameCollection })
{ {
self.pageControl.currentPage = index self.pageControl.currentPage = index
} }
@ -216,31 +216,31 @@ private extension GamesViewController
if sections > 0 if sections > 0
{ {
// Reset page view controller if currently hidden or current child should view controller no longer exists // Reset page view controller if currently hidden or current child should view controller no longer exists
if self.pageViewController.view.hidden || resetPageViewController if self.pageViewController.view.isHidden || resetPageViewController
{ {
if let viewController = self.viewControllerForIndex(0) if let viewController = self.viewControllerForIndex(0)
{ {
self.pageViewController.view.hidden = false self.pageViewController.view.isHidden = false
self.backgroundView.hidden = true self.backgroundView.isHidden = true
self.pageViewController.setViewControllers([viewController], direction: .Forward, animated: false, completion: nil) self.pageViewController.setViewControllers([viewController], direction: .forward, animated: false, completion: nil)
self.title = viewController.title self.title = viewController.title
} }
} }
else else
{ {
self.pageViewController.setViewControllers(self.pageViewController.viewControllers, direction: .Forward, animated: false, completion: nil) self.pageViewController.setViewControllers(self.pageViewController.viewControllers, direction: .forward, animated: false, completion: nil)
} }
} }
else else
{ {
self.title = NSLocalizedString("Games", comment: "") self.title = NSLocalizedString("Games", comment: "")
if !self.pageViewController.view.hidden if !self.pageViewController.view.isHidden
{ {
self.pageViewController.view.hidden = true self.pageViewController.view.isHidden = true
self.backgroundView.hidden = false self.backgroundView.isHidden = false
} }
} }
} }
@ -248,7 +248,7 @@ private extension GamesViewController
extension GamesViewController: GamePickerControllerDelegate extension GamesViewController: GamePickerControllerDelegate
{ {
func gamePickerController(gamePickerController: GamePickerController, didImportGames games: [Game]) func gamePickerController(_ gamePickerController: GamePickerController, didImportGames games: [Game])
{ {
print(games) print(games)
} }
@ -256,23 +256,23 @@ extension GamesViewController: GamePickerControllerDelegate
extension GamesViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource extension GamesViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource
{ {
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?
{ {
let viewController = self.viewControllerForIndex(self.pageControl.currentPage - 1) let viewController = self.viewControllerForIndex(self.pageControl.currentPage - 1)
return viewController return viewController
} }
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?
{ {
let viewController = self.viewControllerForIndex(self.pageControl.currentPage + 1) let viewController = self.viewControllerForIndex(self.pageControl.currentPage + 1)
return viewController return viewController
} }
func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) 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? GamesCollectionViewController, let gameCollection = viewController.gameCollection
{ {
let index = self.fetchedResultsController.fetchedObjects?.indexOf({ $0 as! GameCollection == gameCollection }) ?? 0 let index = self.fetchedResultsController.fetchedObjects?.index(where: { $0 as! GameCollection == gameCollection }) ?? 0
self.pageControl.currentPage = index self.pageControl.currentPage = index
} }
@ -282,7 +282,7 @@ extension GamesViewController: UIPageViewControllerDelegate, UIPageViewControlle
extension GamesViewController: NSFetchedResultsControllerDelegate extension GamesViewController: NSFetchedResultsControllerDelegate
{ {
func controllerDidChangeContent(controller: NSFetchedResultsController) func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
{ {
self.updateSections() self.updateSections()
} }

View File

@ -23,7 +23,7 @@ class CheatTextView: UITextView
} }
} }
@NSCopying private var attributedFormat: NSAttributedString? @NSCopying private var attributedFormat: AttributedString?
required init?(coder aDecoder: NSCoder) required init?(coder aDecoder: NSCoder)
{ {
@ -44,7 +44,7 @@ extension CheatTextView
if let format = self.cheatFormat, font = self.font if let format = self.cheatFormat, font = self.font
{ {
let characterWidth = ("A" as NSString).sizeWithAttributes([NSFontAttributeName: font]).width let characterWidth = ("A" as NSString).size(attributes: [NSFontAttributeName: font]).width
let width = characterWidth * CGFloat(format.format.characters.count) let width = characterWidth * CGFloat(format.format.characters.count)
self.textContainer.size = CGSize(width: width, height: 0) self.textContainer.size = CGSize(width: width, height: 0)
@ -65,13 +65,13 @@ private extension CheatTextView
let attributedFormat = NSMutableAttributedString() let attributedFormat = NSMutableAttributedString()
var prefixString: NSString? = nil var prefixString: NSString? = nil
let scanner = NSScanner(string: format) let scanner = Scanner(string: format)
scanner.charactersToBeSkipped = nil scanner.charactersToBeSkipped = nil
while (!scanner.atEnd) while (!scanner.isAtEnd)
{ {
var string: NSString? = nil var string: NSString? = nil
scanner.scanCharactersFromSet(NSCharacterSet.alphanumericCharacterSet(), intoString: &string) scanner.scanCharacters(from: CharacterSet.alphanumerics, into: &string)
guard let scannedString = string where scannedString.length > 0 else { break } guard let scannedString = string where scannedString.length > 0 else { break }
@ -82,10 +82,10 @@ private extension CheatTextView
attributedString.addAttribute(CheatPrefixAttribute, value: prefixString, range: NSRange(location: 0, length: 1)) attributedString.addAttribute(CheatPrefixAttribute, value: prefixString, range: NSRange(location: 0, length: 1))
} }
attributedFormat.appendAttributedString(attributedString) attributedFormat.append(attributedString)
prefixString = nil prefixString = nil
scanner.scanUpToCharactersFromSet(NSCharacterSet.alphanumericCharacterSet(), intoString: &prefixString) scanner.scanUpToCharacters(from: CharacterSet.alphanumerics, into: &prefixString)
} }
self.attributedFormat = attributedFormat self.attributedFormat = attributedFormat
@ -95,17 +95,17 @@ private extension CheatTextView
self.layoutIfNeeded() self.layoutIfNeeded()
let range = NSRange(location: 0, length: (self.text as NSString).length) let range = NSRange(location: 0, length: (self.text as NSString).length)
self.layoutManager.invalidateGlyphsForCharacterRange(range, changeInLength: 0, actualCharacterRange: nil) self.layoutManager.invalidateGlyphs(forCharacterRange: range, changeInLength: 0, actualCharacterRange: nil)
self.layoutManager.invalidateLayoutForCharacterRange(range, actualCharacterRange: nil) self.layoutManager.invalidateLayout(forCharacterRange: range, actualCharacterRange: nil)
self.layoutManager.ensureGlyphsForCharacterRange(range) self.layoutManager.ensureGlyphs(forCharacterRange: range)
self.layoutManager.ensureLayoutForCharacterRange(range) self.layoutManager.ensureLayout(forCharacterRange: range)
} }
} }
} }
extension CheatTextView: NSLayoutManagerDelegate extension CheatTextView: NSLayoutManagerDelegate
{ {
func layoutManager(layoutManager: NSLayoutManager, shouldGenerateGlyphs glyphs: UnsafePointer<CGGlyph>, properties props: UnsafePointer<NSGlyphProperty>, characterIndexes charIndexes: UnsafePointer<Int>, font aFont: UIFont, forGlyphRange glyphRange: NSRange) -> Int func layoutManager(_ layoutManager: NSLayoutManager, shouldGenerateGlyphs glyphs: UnsafePointer<CGGlyph>, properties props: UnsafePointer<NSGlyphProperty>, characterIndexes charIndexes: UnsafePointer<Int>, font aFont: UIFont, forGlyphRange glyphRange: NSRange) -> Int
{ {
// Returning 0 = let the layoutManager do the normal logic // Returning 0 = let the layoutManager do the normal logic
guard let attributedFormat = self.attributedFormat else { return 0 } guard let attributedFormat = self.attributedFormat else { return 0 }
@ -117,9 +117,9 @@ extension CheatTextView: NSLayoutManagerDelegate
let bufferSize = max(attributedFormat.length + 1, glyphCount * 2) let bufferSize = max(attributedFormat.length + 1, glyphCount * 2)
// Allocate our replacement buffers // Allocate our replacement buffers
let glyphBuffer = UnsafeMutablePointer<CGGlyph>.alloc(bufferSize) let glyphBuffer = UnsafeMutablePointer<CGGlyph>(allocatingCapacity: bufferSize)
let propertyBuffer = UnsafeMutablePointer<NSGlyphProperty>.alloc(bufferSize) let propertyBuffer = UnsafeMutablePointer<NSGlyphProperty>(allocatingCapacity: bufferSize)
let characterBuffer = UnsafeMutablePointer<Int>.alloc(bufferSize) let characterBuffer = UnsafeMutablePointer<Int>(allocatingCapacity: bufferSize)
var offset = 0 var offset = 0
@ -128,7 +128,7 @@ extension CheatTextView: NSLayoutManagerDelegate
// The index the actual character maps to in the cheat format // The index the actual character maps to in the cheat format
let characterIndex = charIndexes[i] % attributedFormat.length let characterIndex = charIndexes[i] % attributedFormat.length
if let prefix = attributedFormat.attributesAtIndex(characterIndex, effectiveRange: nil)[CheatPrefixAttribute] as? String if let prefix = attributedFormat.attributes(at: characterIndex, effectiveRange: nil)[CheatPrefixAttribute] as? String
{ {
// If there is a prefix string, we insert the glyphs (and associated properties/character indexes) first // If there is a prefix string, we insert the glyphs (and associated properties/character indexes) first
let prefixCount = prefix.characters.count let prefixCount = prefix.characters.count
@ -139,7 +139,7 @@ extension CheatTextView: NSLayoutManagerDelegate
propertyBuffer[i + offset + j] = props[i] propertyBuffer[i + offset + j] = props[i]
// Prepend prefix character // Prepend prefix character
var prefixCharacter = (prefix as NSString).characterAtIndex(0) var prefixCharacter = (prefix as NSString).character(at: 0)
CTFontGetGlyphsForCharacters(aFont as CTFont, &prefixCharacter, glyphBuffer + (i + offset + j), 1) CTFontGetGlyphsForCharacters(aFont as CTFont, &prefixCharacter, glyphBuffer + (i + offset + j), 1)
} }
@ -156,9 +156,9 @@ extension CheatTextView: NSLayoutManagerDelegate
layoutManager.setGlyphs(glyphBuffer, properties: propertyBuffer, characterIndexes: characterBuffer, font: aFont, forGlyphRange: NSRange(location: glyphRange.location, length: glyphCount + offset)) layoutManager.setGlyphs(glyphBuffer, properties: propertyBuffer, characterIndexes: characterBuffer, font: aFont, forGlyphRange: NSRange(location: glyphRange.location, length: glyphCount + offset))
// Clean up memory // Clean up memory
characterBuffer.dealloc(bufferSize) characterBuffer.deallocateCapacity(bufferSize)
propertyBuffer.dealloc(bufferSize) propertyBuffer.deallocateCapacity(bufferSize)
glyphBuffer.dealloc(bufferSize) glyphBuffer.deallocateCapacity(bufferSize)
// Return total number of glyphs // Return total number of glyphs
return glyphCount + offset return glyphCount + offset

View File

@ -15,9 +15,9 @@ import Roxas
protocol CheatsViewControllerDelegate: class protocol CheatsViewControllerDelegate: class
{ {
func cheatsViewControllerActiveEmulatorCore(saveStatesViewController: CheatsViewController) -> EmulatorCore func cheatsViewControllerActiveEmulatorCore(_ saveStatesViewController: CheatsViewController) -> EmulatorCore
func cheatsViewController(cheatsViewController: CheatsViewController, didActivateCheat cheat: Cheat) throws func cheatsViewController(_ cheatsViewController: CheatsViewController, didActivateCheat cheat: Cheat) throws
func cheatsViewController(cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat) func cheatsViewController(_ cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat)
} }
class CheatsViewController: UITableViewController class CheatsViewController: UITableViewController
@ -30,7 +30,7 @@ class CheatsViewController: UITableViewController
private var backgroundView: RSTBackgroundView! private var backgroundView: RSTBackgroundView!
private var fetchedResultsController: NSFetchedResultsController! private var fetchedResultsController: NSFetchedResultsController<AnyObject>!
} }
extension CheatsViewController extension CheatsViewController
@ -42,18 +42,18 @@ extension CheatsViewController
self.title = NSLocalizedString("Cheats", comment: "") self.title = NSLocalizedString("Cheats", comment: "")
self.backgroundView = RSTBackgroundView(frame: self.view.bounds) self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
self.backgroundView.hidden = false self.backgroundView.isHidden = false
self.backgroundView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] self.backgroundView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.backgroundView.textLabel.text = NSLocalizedString("No Cheats", comment: "") self.backgroundView.textLabel.text = NSLocalizedString("No Cheats", comment: "")
self.backgroundView.textLabel.textColor = UIColor.whiteColor() self.backgroundView.textLabel.textColor = UIColor.white()
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can add a new cheat by pressing the + button in the top right.", comment: "") self.backgroundView.detailTextLabel.text = NSLocalizedString("You can add a new cheat by pressing the + button in the top right.", comment: "")
self.backgroundView.detailTextLabel.textColor = UIColor.whiteColor() self.backgroundView.detailTextLabel.textColor = UIColor.white()
self.tableView.backgroundView = self.backgroundView self.tableView.backgroundView = self.backgroundView
self.registerForPreviewingWithDelegate(self, sourceView: self.tableView) self.registerForPreviewing(with: self, sourceView: self.tableView)
} }
override func viewWillAppear(animated: Bool) override func viewWillAppear(_ animated: Bool)
{ {
self.fetchedResultsController.performFetchIfNeeded() self.fetchedResultsController.performFetchIfNeeded()
@ -72,7 +72,7 @@ extension CheatsViewController
//MARK: - Navigation - //MARK: - Navigation -
private extension CheatsViewController private extension CheatsViewController
{ {
@IBAction func unwindFromEditCheatViewController(segue: UIStoryboardSegue) @IBAction func unwindFromEditCheatViewController(_ segue: UIStoryboardSegue)
{ {
} }
@ -87,8 +87,8 @@ private extension CheatsViewController
let fetchRequest = Cheat.fetchRequest() let fetchRequest = Cheat.fetchRequest()
fetchRequest.returnsObjectsAsFaults = false fetchRequest.returnsObjectsAsFaults = false
fetchRequest.predicate = NSPredicate(format: "%K == %@", Cheat.Attributes.game.rawValue, game) fetchRequest.predicate = Predicate(format: "%K == %@", Cheat.Attributes.game.rawValue, game)
fetchRequest.sortDescriptors = [NSSortDescriptor(key: Cheat.Attributes.name.rawValue, ascending: true)] fetchRequest.sortDescriptors = [SortDescriptor(key: Cheat.Attributes.name.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: nil, cacheName: nil)
self.fetchedResultsController.delegate = self self.fetchedResultsController.delegate = self
@ -98,13 +98,13 @@ private extension CheatsViewController
{ {
if let fetchedObjects = self.fetchedResultsController.fetchedObjects where fetchedObjects.count > 0 if let fetchedObjects = self.fetchedResultsController.fetchedObjects where fetchedObjects.count > 0
{ {
self.tableView.separatorStyle = .SingleLine self.tableView.separatorStyle = .singleLine
self.backgroundView.hidden = true self.backgroundView.isHidden = true
} }
else else
{ {
self.tableView.separatorStyle = .None self.tableView.separatorStyle = .none
self.backgroundView.hidden = false self.backgroundView.isHidden = false
} }
} }
} }
@ -119,14 +119,14 @@ private extension CheatsViewController
editCheatViewController.presentWithPresentingViewController(self) editCheatViewController.presentWithPresentingViewController(self)
} }
func deleteCheat(cheat: Cheat) func deleteCheat(_ cheat: Cheat)
{ {
self.delegate.cheatsViewController(self, didDeactivateCheat: cheat) self.delegate.cheatsViewController(self, didDeactivateCheat: cheat)
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext() let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlock { backgroundContext.perform {
let temporaryCheat = backgroundContext.objectWithID(cheat.objectID) let temporaryCheat = backgroundContext.object(with: cheat.objectID)
backgroundContext.deleteObject(temporaryCheat) backgroundContext.delete(temporaryCheat)
backgroundContext.saveWithErrorLogging() backgroundContext.saveWithErrorLogging()
} }
} }
@ -136,17 +136,17 @@ private extension CheatsViewController
/// Convenience /// Convenience
private extension CheatsViewController private extension CheatsViewController
{ {
func configure(cell cell: UITableViewCell, forIndexPath indexPath: NSIndexPath) func configure(cell: UITableViewCell, forIndexPath indexPath: IndexPath)
{ {
let cheat = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Cheat let cheat = self.fetchedResultsController.object(at: indexPath) as! Cheat
cell.textLabel?.text = cheat.name cell.textLabel?.text = cheat.name
cell.textLabel?.font = UIFont.boldSystemFontOfSize(cell.textLabel!.font.pointSize) cell.textLabel?.font = UIFont.boldSystemFont(ofSize: cell.textLabel!.font.pointSize)
cell.accessoryType = cheat.enabled ? .Checkmark : .None cell.accessoryType = cheat.enabled ? .checkmark : .none
} }
func makeEditCheatViewController(cheat cheat: Cheat?) -> EditCheatViewController func makeEditCheatViewController(cheat: Cheat?) -> EditCheatViewController
{ {
let editCheatViewController = self.storyboard!.instantiateViewControllerWithIdentifier("editCheatViewController") as! EditCheatViewController let editCheatViewController = self.storyboard!.instantiateViewController(withIdentifier: "editCheatViewController") as! EditCheatViewController
editCheatViewController.delegate = self editCheatViewController.delegate = self
editCheatViewController.supportedCheatFormats = self.delegate.cheatsViewControllerActiveEmulatorCore(self).supportedCheatFormats editCheatViewController.supportedCheatFormats = self.delegate.cheatsViewControllerActiveEmulatorCore(self).supportedCheatFormats
editCheatViewController.cheat = cheat editCheatViewController.cheat = cheat
@ -160,21 +160,21 @@ extension CheatsViewController
{ {
// MARK: - Table view data source // MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int override func numberOfSections(in tableView: UITableView) -> Int
{ {
let numberOfSections = self.fetchedResultsController.sections!.count let numberOfSections = self.fetchedResultsController.sections!.count
return numberOfSections return numberOfSections
} }
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{ {
let section = self.fetchedResultsController.sections![section] let section = self.fetchedResultsController.sections![section]
return section.numberOfObjects return section.numberOfObjects
} }
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{ {
let cell = tableView.dequeueReusableCellWithIdentifier(RSTGenericCellIdentifier, forIndexPath: indexPath) let cell = tableView.dequeueReusableCell(withIdentifier: RSTGenericCellIdentifier, for: indexPath)
self.configure(cell: cell, forIndexPath: indexPath) self.configure(cell: cell, forIndexPath: indexPath)
return cell return cell
} }
@ -182,13 +182,13 @@ extension CheatsViewController
extension CheatsViewController extension CheatsViewController
{ {
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{ {
let cheat = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Cheat let cheat = self.fetchedResultsController.object(at: indexPath) as! Cheat
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext() let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlockAndWait { backgroundContext.performAndWait {
let temporaryCheat = backgroundContext.objectWithID(cheat.objectID) as! Cheat let temporaryCheat = backgroundContext.object(with: cheat.objectID) as! Cheat
temporaryCheat.enabled = !temporaryCheat.enabled temporaryCheat.enabled = !temporaryCheat.enabled
if temporaryCheat.enabled if temporaryCheat.enabled
@ -215,18 +215,18 @@ extension CheatsViewController
backgroundContext.saveWithErrorLogging() backgroundContext.saveWithErrorLogging()
} }
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None) self.tableView.reloadRows(at: [indexPath], with: .none)
} }
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
{ {
let cheat = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Cheat let cheat = self.fetchedResultsController.object(at: indexPath) as! Cheat
let deleteAction = UITableViewRowAction(style: .Destructive, title: NSLocalizedString("Delete", comment: "")) { (action, indexPath) in let deleteAction = UITableViewRowAction(style: UITableViewRowActionStyle(), title: NSLocalizedString("Delete", comment: "")) { (action, indexPath) in
self.deleteCheat(cheat) self.deleteCheat(cheat)
} }
let editAction = UITableViewRowAction(style: .Normal, title: NSLocalizedString("Edit", comment: "")) { (action, indexPath) in let editAction = UITableViewRowAction(style: .normal, title: NSLocalizedString("Edit", comment: "")) { (action, indexPath) in
let editCheatViewController = self.makeEditCheatViewController(cheat: cheat) let editCheatViewController = self.makeEditCheatViewController(cheat: cheat)
editCheatViewController.presentWithPresentingViewController(self) editCheatViewController.presentWithPresentingViewController(self)
} }
@ -234,7 +234,7 @@ extension CheatsViewController
return [deleteAction, editAction] return [deleteAction, editAction]
} }
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
{ {
// This method intentionally left blank because someone decided it was a Good Idea to require this method be implemented to use UITableViewRowActions // This method intentionally left blank because someone decided it was a Good Idea to require this method be implemented to use UITableViewRowActions
} }
@ -243,20 +243,20 @@ extension CheatsViewController
//MARK: - <UIViewControllerPreviewingDelegate> - //MARK: - <UIViewControllerPreviewingDelegate> -
extension CheatsViewController: UIViewControllerPreviewingDelegate extension CheatsViewController: UIViewControllerPreviewingDelegate
{ {
func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?
{ {
guard let indexPath = self.tableView.indexPathForRowAtPoint(location) else { return nil } guard let indexPath = self.tableView.indexPathForRow(at: location) else { return nil }
let frame = self.tableView.rectForRowAtIndexPath(indexPath) let frame = self.tableView.rectForRow(at: indexPath)
previewingContext.sourceRect = frame previewingContext.sourceRect = frame
let cheat = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Cheat let cheat = self.fetchedResultsController.object(at: indexPath) as! Cheat
let editCheatViewController = self.makeEditCheatViewController(cheat: cheat) let editCheatViewController = self.makeEditCheatViewController(cheat: cheat)
return editCheatViewController return editCheatViewController
} }
func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController)
{ {
let editCheatViewController = viewControllerToCommit as! EditCheatViewController let editCheatViewController = viewControllerToCommit as! EditCheatViewController
editCheatViewController.presentWithPresentingViewController(self) editCheatViewController.presentWithPresentingViewController(self)
@ -266,7 +266,7 @@ extension CheatsViewController: UIViewControllerPreviewingDelegate
//MARK: - <EditCheatViewControllerDelegate> - //MARK: - <EditCheatViewControllerDelegate> -
extension CheatsViewController: EditCheatViewControllerDelegate extension CheatsViewController: EditCheatViewControllerDelegate
{ {
func editCheatViewController(editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?) throws func editCheatViewController(_ editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?) throws
{ {
try self.delegate.cheatsViewController(self, didActivateCheat: cheat) try self.delegate.cheatsViewController(self, didActivateCheat: cheat)
@ -274,7 +274,7 @@ extension CheatsViewController: EditCheatViewControllerDelegate
{ {
let code = cheat.code let code = cheat.code
previousCheat.managedObjectContext?.performBlockAndWait({ previousCheat.managedObjectContext?.performAndWait({
guard previousCheat.code != code else { return } guard previousCheat.code != code else { return }
@ -283,7 +283,7 @@ extension CheatsViewController: EditCheatViewControllerDelegate
} }
} }
func editCheatViewController(editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat) func editCheatViewController(_ editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat)
{ {
self.delegate.cheatsViewController(self, didDeactivateCheat: cheat) self.delegate.cheatsViewController(self, didDeactivateCheat: cheat)
} }
@ -292,7 +292,7 @@ extension CheatsViewController: EditCheatViewControllerDelegate
//MARK: - <NSFetchedResultsControllerDelegate> - //MARK: - <NSFetchedResultsControllerDelegate> -
extension CheatsViewController: NSFetchedResultsControllerDelegate extension CheatsViewController: NSFetchedResultsControllerDelegate
{ {
func controllerDidChangeContent(controller: NSFetchedResultsController) func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
{ {
self.tableView.reloadData() self.tableView.reloadData()
self.updateBackgroundView() self.updateBackgroundView()

View File

@ -14,13 +14,13 @@ import Roxas
protocol EditCheatViewControllerDelegate: class protocol EditCheatViewControllerDelegate: class
{ {
func editCheatViewController(editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?) throws func editCheatViewController(_ editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?) throws
func editCheatViewController(editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat) func editCheatViewController(_ editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat)
} }
private extension EditCheatViewController private extension EditCheatViewController
{ {
enum ValidationError: ErrorType enum ValidationError: ErrorProtocol
{ {
case invalidCode case invalidCode
case duplicateName case duplicateName
@ -66,18 +66,18 @@ extension EditCheatViewController
var type: CheatType! var type: CheatType!
var code: String! var code: String!
self.managedObjectContext.performBlockAndWait { self.managedObjectContext.performAndWait {
// Main Thread context is read-only, so we either create a new cheat, or get a reference to the current cheat in a new background context // Main Thread context is read-only, so we either create a new cheat, or get a reference to the current cheat in a new background context
if let cheat = self.cheat if let cheat = self.cheat
{ {
self.mutableCheat = self.managedObjectContext.objectWithID(cheat.objectID) as? Cheat self.mutableCheat = self.managedObjectContext.object(with: cheat.objectID) as? Cheat
} }
else else
{ {
self.mutableCheat = Cheat.insertIntoManagedObjectContext(self.managedObjectContext) self.mutableCheat = Cheat.insertIntoManagedObjectContext(self.managedObjectContext)
self.mutableCheat.game = self.managedObjectContext.objectWithID(self.game.objectID) as! Game self.mutableCheat.game = self.managedObjectContext.object(with: self.game.objectID) as! Game
self.mutableCheat.type = self.supportedCheatFormats.first!.type self.mutableCheat.type = self.supportedCheatFormats.first!.type
self.mutableCheat.code = "" self.mutableCheat.code = ""
self.mutableCheat.name = "" self.mutableCheat.name = ""
@ -107,12 +107,12 @@ extension EditCheatViewController
self.typeSegmentedControl.removeAllSegments() self.typeSegmentedControl.removeAllSegments()
for (index, format) in self.supportedCheatFormats.enumerate() for (index, format) in self.supportedCheatFormats.enumerated()
{ {
self.typeSegmentedControl.insertSegmentWithTitle(format.name, atIndex: index, animated: false) self.typeSegmentedControl.insertSegment(withTitle: format.name, at: index, animated: false)
} }
if let index = self.supportedCheatFormats.indexOf({ $0.type == type }) if let index = self.supportedCheatFormats.index(where: { $0.type == type })
{ {
self.typeSegmentedControl.selectedSegmentIndex = index self.typeSegmentedControl.selectedSegmentIndex = index
} }
@ -125,13 +125,13 @@ extension EditCheatViewController
self.updateSaveButtonState() self.updateSaveButtonState()
} }
override func viewDidAppear(animated: Bool) override func viewDidAppear(_ animated: Bool)
{ {
super.viewDidAppear(animated) super.viewDidAppear(animated)
// This matters when going from peek -> pop // This matters when going from peek -> pop
// Otherwise, has no effect because viewDidLayoutSubviews has already been called // Otherwise, has no effect because viewDidLayoutSubviews has already been called
if self.appearing && !self.isPreviewing if self.isAppearing && !self.isPreviewing
{ {
self.nameTextField.becomeFirstResponder() self.nameTextField.becomeFirstResponder()
} }
@ -149,7 +149,7 @@ extension EditCheatViewController
self.codeTextView.textContainer.lineFragmentPadding = 0 self.codeTextView.textContainer.lineFragmentPadding = 0
} }
if self.appearing && !self.isPreviewing if self.isAppearing && !self.isPreviewing
{ {
self.nameTextField.becomeFirstResponder() self.nameTextField.becomeFirstResponder()
} }
@ -159,35 +159,35 @@ extension EditCheatViewController
{ {
guard let cheat = self.cheat else { return [] } guard let cheat = self.cheat else { return [] }
let copyCodeAction = UIPreviewAction(title: NSLocalizedString("Copy Code", comment: ""), style: .Default) { (action, viewController) in let copyCodeAction = UIPreviewAction(title: NSLocalizedString("Copy Code", comment: ""), style: .default) { (action, viewController) in
UIPasteboard.generalPasteboard().string = cheat.code UIPasteboard.general().string = cheat.code
} }
let presentingViewController = self.presentingViewController! let presentingViewController = self.presentingViewController!
let editCheatAction = UIPreviewAction(title: NSLocalizedString("Edit", comment: ""), style: .Default) { (action, viewController) in let editCheatAction = UIPreviewAction(title: NSLocalizedString("Edit", comment: ""), style: .default) { (action, viewController) in
// Delaying until next run loop prevents self from being dismissed immediately // Delaying until next run loop prevents self from being dismissed immediately
dispatch_async(dispatch_get_main_queue()) { DispatchQueue.main.async {
let editCheatViewController = viewController as! EditCheatViewController let editCheatViewController = viewController as! EditCheatViewController
editCheatViewController.presentWithPresentingViewController(presentingViewController) editCheatViewController.presentWithPresentingViewController(presentingViewController)
} }
} }
let deleteAction = UIPreviewAction(title: NSLocalizedString("Delete", comment: ""), style: .Destructive) { [unowned self] (action, viewController) in let deleteAction = UIPreviewAction(title: NSLocalizedString("Delete", comment: ""), style: .destructive) { [unowned self] (action, viewController) in
self.delegate?.editCheatViewController(self, deactivateCheat: cheat) self.delegate?.editCheatViewController(self, deactivateCheat: cheat)
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext() let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlock { backgroundContext.perform {
let temporaryCheat = backgroundContext.objectWithID(cheat.objectID) let temporaryCheat = backgroundContext.object(with: cheat.objectID)
backgroundContext.deleteObject(temporaryCheat) backgroundContext.delete(temporaryCheat)
backgroundContext.saveWithErrorLogging() backgroundContext.saveWithErrorLogging()
} }
} }
let cancelDeleteAction = UIPreviewAction(title: NSLocalizedString("Cancel", comment: ""), style: .Default) { (action, viewController) in let cancelDeleteAction = UIPreviewAction(title: NSLocalizedString("Cancel", comment: ""), style: .default) { (action, viewController) in
} }
let deleteActionGroup = UIPreviewActionGroup(title: NSLocalizedString("Delete", comment: ""), style: .Destructive, actions: [deleteAction, cancelDeleteAction]) let deleteActionGroup = UIPreviewActionGroup(title: NSLocalizedString("Delete", comment: ""), style: .destructive, actions: [deleteAction, cancelDeleteAction])
return [copyCodeAction, editCheatAction, deleteActionGroup] return [copyCodeAction, editCheatAction, deleteActionGroup]
} }
@ -198,7 +198,7 @@ extension EditCheatViewController
// Dispose of any resources that can be recreated. // Dispose of any resources that can be recreated.
} }
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
{ {
self.nameTextField.resignFirstResponder() self.nameTextField.resignFirstResponder()
self.codeTextView.resignFirstResponder() self.codeTextView.resignFirstResponder()
@ -207,19 +207,19 @@ extension EditCheatViewController
internal extension EditCheatViewController internal extension EditCheatViewController
{ {
func presentWithPresentingViewController(presentingViewController: UIViewController) func presentWithPresentingViewController(_ presentingViewController: UIViewController)
{ {
let navigationController = RSTNavigationController(rootViewController: self) let navigationController = RSTNavigationController(rootViewController: self)
navigationController.modalPresentationStyle = .OverFullScreen // Keeps PausePresentationController active to ensure layout is not messed up navigationController.modalPresentationStyle = .overFullScreen // Keeps PausePresentationController active to ensure layout is not messed up
navigationController.modalPresentationCapturesStatusBarAppearance = true navigationController.modalPresentationCapturesStatusBarAppearance = true
presentingViewController.presentViewController(navigationController, animated: true, completion: nil) presentingViewController.present(navigationController, animated: true, completion: nil)
} }
} }
private extension EditCheatViewController private extension EditCheatViewController
{ {
@IBAction func updateCheatName(sender: UITextField) @IBAction func updateCheatName(_ sender: UITextField)
{ {
var title = sender.text ?? "" var title = sender.text ?? ""
if title.characters.count == 0 if title.characters.count == 0
@ -232,17 +232,17 @@ private extension EditCheatViewController
self.updateSaveButtonState() self.updateSaveButtonState()
} }
@IBAction func updateCheatType(sender: UISegmentedControl) @IBAction func updateCheatType(_ sender: UISegmentedControl)
{ {
self.codeTextView.cheatFormat = self.selectedCheatFormat self.codeTextView.cheatFormat = self.selectedCheatFormat
UIView.performWithoutAnimation { UIView.performWithoutAnimation {
self.tableView.reloadSections(NSIndexSet(index: Section.type.rawValue), withRowAnimation: .None) self.tableView.reloadSections(IndexSet(integer: Section.type.rawValue), with: .none)
// Hacky-ish workaround so we can update the footer text for the code section without causing text view to resign first responder status // Hacky-ish workaround so we can update the footer text for the code section without causing text view to resign first responder status
self.tableView.beginUpdates() self.tableView.beginUpdates()
if let footerView = self.tableView.footerViewForSection(Section.code.rawValue) if let footerView = self.tableView.footerView(forSection: Section.code.rawValue)
{ {
footerView.textLabel!.text = self.tableView(self.tableView, titleForFooterInSection: Section.code.rawValue) footerView.textLabel!.text = self.tableView(self.tableView, titleForFooterInSection: Section.code.rawValue)
footerView.sizeToFit() footerView.sizeToFit()
@ -257,12 +257,12 @@ private extension EditCheatViewController
let isValidName = !(self.nameTextField.text ?? "").isEmpty let isValidName = !(self.nameTextField.text ?? "").isEmpty
let isValidCode = !self.codeTextView.text.isEmpty let isValidCode = !self.codeTextView.text.isEmpty
self.navigationItem.rightBarButtonItem?.enabled = isValidName && isValidCode self.navigationItem.rightBarButtonItem?.isEnabled = isValidName && isValidCode
} }
@IBAction func saveCheat(sender: UIBarButtonItem) @IBAction func saveCheat(_ sender: UIBarButtonItem)
{ {
self.mutableCheat.managedObjectContext?.performBlockAndWait { self.mutableCheat.managedObjectContext?.performAndWait {
self.mutableCheat.name = self.nameTextField.text ?? "" self.mutableCheat.name = self.nameTextField.text ?? ""
self.mutableCheat.type = self.selectedCheatFormat.type self.mutableCheat.type = self.selectedCheatFormat.type
@ -272,7 +272,7 @@ private extension EditCheatViewController
{ {
try self.validateCheat(self.mutableCheat) try self.validateCheat(self.mutableCheat)
self.mutableCheat.managedObjectContext?.saveWithErrorLogging() self.mutableCheat.managedObjectContext?.saveWithErrorLogging()
self.performSegueWithIdentifier("unwindEditCheatSegue", sender: sender) self.performSegue(withIdentifier: "unwindEditCheatSegue", sender: sender)
} }
catch ValidationError.invalidCode catch ValidationError.invalidCode
{ {
@ -299,13 +299,13 @@ private extension EditCheatViewController
} }
} }
func validateCheat(cheat: Cheat) throws func validateCheat(_ cheat: Cheat) throws
{ {
let name = cheat.name! let name = cheat.name!
let code = cheat.code let code = cheat.code
// Find all cheats that are for the same game, don't have the same identifier as the current cheat, but have either the same name or code // Find all cheats that are for the same game, don't have the same identifier as the current cheat, but have either the same name or code
let predicate = NSPredicate(format: "%K == %@ AND %K != %@ AND (%K == %@ OR %K == %@)", Cheat.Attributes.game.rawValue, cheat.game, Cheat.Attributes.identifier.rawValue, cheat.identifier, Cheat.Attributes.code.rawValue, code, Cheat.Attributes.name.rawValue, name) let predicate = Predicate(format: "%K == %@ AND %K != %@ AND (%K == %@ OR %K == %@)", Cheat.Attributes.game.rawValue, cheat.game, Cheat.Attributes.identifier.rawValue, cheat.identifier, Cheat.Attributes.code.rawValue, code, Cheat.Attributes.name.rawValue, name)
let cheats = Cheat.instancesWithPredicate(predicate, inManagedObjectContext: self.managedObjectContext, type: Cheat.self) let cheats = Cheat.instancesWithPredicate(predicate, inManagedObjectContext: self.managedObjectContext, type: Cheat.self)
for cheat in cheats for cheat in cheats
@ -330,26 +330,26 @@ private extension EditCheatViewController
} }
} }
@IBAction func textFieldDidEndEditing(sender: UITextField) @IBAction func textFieldDidEndEditing(_ sender: UITextField)
{ {
sender.resignFirstResponder() sender.resignFirstResponder()
} }
func presentErrorAlert(title title: String, message: String, handler: (Void -> Void)?) func presentErrorAlert(title: String, message: String, handler: ((Void) -> Void)?)
{ {
dispatch_async(dispatch_get_main_queue()) { DispatchQueue.main.async {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert) let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .Default, handler: { action in alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: { action in
handler?() handler?()
})) }))
self.presentViewController(alertController, animated: true, completion: nil) self.present(alertController, animated: true, completion: nil)
} }
} }
} }
extension EditCheatViewController extension EditCheatViewController
{ {
override func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String? override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String?
{ {
switch Section(rawValue: section)! switch Section(rawValue: section)!
{ {
@ -360,8 +360,8 @@ extension EditCheatViewController
return title return title
case .code: case .code:
let containsSpaces = self.selectedCheatFormat.format.containsString(" ") let containsSpaces = self.selectedCheatFormat.format.contains(" ")
let containsDashes = self.selectedCheatFormat.format.containsString("-") let containsDashes = self.selectedCheatFormat.format.contains("-")
switch (containsSpaces, containsDashes) switch (containsSpaces, containsDashes)
{ {
@ -376,7 +376,7 @@ extension EditCheatViewController
extension EditCheatViewController: UITextViewDelegate extension EditCheatViewController: UITextViewDelegate
{ {
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool
{ {
defer { self.updateSaveButtonState() } defer { self.updateSaveButtonState() }
@ -392,8 +392,8 @@ extension EditCheatViewController: UITextViewDelegate
// We need to manually add back the attributes when manually modifying the underlying text storage // We need to manually add back the attributes when manually modifying the underlying text storage
// Otherwise, pasting text into an empty text view will result in the wrong font being used // Otherwise, pasting text into an empty text view will result in the wrong font being used
let attributedString = NSAttributedString(string: sanitizedText, attributes: textView.typingAttributes) let attributedString = AttributedString(string: sanitizedText, attributes: textView.typingAttributes)
textView.textStorage.replaceCharactersInRange(range, withAttributedString: attributedString) textView.textStorage.replaceCharacters(in: range, with: attributedString)
// We must add attributedString.length, not range.length, in case the attributed string's length differs // We must add attributedString.length, not range.length, in case the attributed string's length differs
textView.selectedRange = NSRange(location: range.location + attributedString.length, length: 0) textView.selectedRange = NSRange(location: range.location + attributedString.length, length: 0)

View File

@ -12,11 +12,11 @@ struct PauseItem: Equatable
{ {
let image: UIImage let image: UIImage
let text: String let text: String
let action: (PauseItem -> Void) let action: ((PauseItem) -> Void)
var selected = false var selected = false
init(image: UIImage, text: String, action: (PauseItem -> Void)) init(image: UIImage, text: String, action: ((PauseItem) -> Void))
{ {
self.image = image self.image = image
self.text = text self.text = text

View File

@ -27,11 +27,11 @@ class PauseMenuViewController: UICollectionViewController
override var preferredContentSize: CGSize { override var preferredContentSize: CGSize {
set { } set { }
get { return self.collectionView?.contentSize ?? CGSizeZero } get { return self.collectionView?.contentSize ?? CGSize.zero }
} }
private var prototypeCell = GridCollectionViewCell() private var prototypeCell = GridCollectionViewCell()
private var previousIndexPath: NSIndexPath? = nil private var previousIndexPath: IndexPath? = nil
} }
extension PauseMenuViewController extension PauseMenuViewController
@ -45,16 +45,16 @@ extension PauseMenuViewController
collectionViewLayout.usesEqualHorizontalSpacingDistributionForSingleRow = true collectionViewLayout.usesEqualHorizontalSpacingDistributionForSingleRow = true
// Manually update prototype cell properties // Manually update prototype cell properties
self.prototypeCell.contentView.widthAnchor.constraintEqualToConstant(collectionViewLayout.itemWidth).active = true self.prototypeCell.contentView.widthAnchor.constraint(equalToConstant: collectionViewLayout.itemWidth).isActive = true
} }
override func viewDidAppear(animated: Bool) override func viewDidAppear(_ animated: Bool)
{ {
super.viewDidAppear(animated) super.viewDidAppear(animated)
if let indexPath = self.previousIndexPath if let indexPath = self.previousIndexPath
{ {
UIView.animateWithDuration(0.2) { UIView.animate(withDuration: 0.2) {
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath) self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
} }
} }
@ -63,54 +63,54 @@ extension PauseMenuViewController
private extension PauseMenuViewController private extension PauseMenuViewController
{ {
func configureCollectionViewCell(cell: GridCollectionViewCell, forIndexPath indexPath: NSIndexPath) func configureCollectionViewCell(_ cell: GridCollectionViewCell, forIndexPath indexPath: IndexPath)
{ {
let pauseItem = self.items[indexPath.item] let pauseItem = self.items[(indexPath as NSIndexPath).item]
cell.maximumImageSize = CGSize(width: 60, height: 60) cell.maximumImageSize = CGSize(width: 60, height: 60)
cell.imageView.image = pauseItem.image cell.imageView.image = pauseItem.image
cell.imageView.contentMode = .Center cell.imageView.contentMode = .center
cell.imageView.layer.borderWidth = 2 cell.imageView.layer.borderWidth = 2
cell.imageView.layer.borderColor = UIColor.whiteColor().CGColor cell.imageView.layer.borderColor = UIColor.white().cgColor
cell.imageView.layer.cornerRadius = 10 cell.imageView.layer.cornerRadius = 10
cell.textLabel.text = pauseItem.text cell.textLabel.text = pauseItem.text
cell.textLabel.textColor = UIColor.whiteColor() cell.textLabel.textColor = UIColor.white()
if pauseItem.selected if pauseItem.selected
{ {
cell.imageView.tintColor = UIColor.blackColor() cell.imageView.tintColor = UIColor.black()
cell.imageView.backgroundColor = UIColor.whiteColor() cell.imageView.backgroundColor = UIColor.white()
} }
else else
{ {
cell.imageView.tintColor = UIColor.whiteColor() cell.imageView.tintColor = UIColor.white()
cell.imageView.backgroundColor = UIColor.clearColor() cell.imageView.backgroundColor = UIColor.clear()
} }
} }
func toggleSelectedStateForPauseItemAtIndexPath(indexPath: NSIndexPath) func toggleSelectedStateForPauseItemAtIndexPath(_ indexPath: IndexPath)
{ {
var pauseItem = self.items[indexPath.item] var pauseItem = self.items[(indexPath as NSIndexPath).item]
pauseItem.selected = !pauseItem.selected pauseItem.selected = !pauseItem.selected
self.items[indexPath.item] = pauseItem self.items[(indexPath as NSIndexPath).item] = pauseItem
let cell = self.collectionView!.cellForItemAtIndexPath(indexPath) as! GridCollectionViewCell let cell = self.collectionView!.cellForItem(at: indexPath) as! GridCollectionViewCell
self.configureCollectionViewCell(cell, forIndexPath: indexPath) self.configureCollectionViewCell(cell, forIndexPath: indexPath)
} }
} }
extension PauseMenuViewController extension PauseMenuViewController
{ {
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{ {
return self.items.count return self.items.count
} }
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{ {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(RSTGenericCellIdentifier, forIndexPath: indexPath) as! GridCollectionViewCell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: RSTGenericCellIdentifier, for: indexPath) as! GridCollectionViewCell
self.configureCollectionViewCell(cell, forIndexPath: indexPath) self.configureCollectionViewCell(cell, forIndexPath: indexPath)
return cell return cell
} }
@ -118,34 +118,34 @@ extension PauseMenuViewController
extension PauseMenuViewController: UICollectionViewDelegateFlowLayout extension PauseMenuViewController: UICollectionViewDelegateFlowLayout
{ {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{ {
self.configureCollectionViewCell(self.prototypeCell, forIndexPath: indexPath) self.configureCollectionViewCell(self.prototypeCell, forIndexPath: indexPath)
let size = self.prototypeCell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize) let size = self.prototypeCell.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
return size return size
} }
} }
extension PauseMenuViewController extension PauseMenuViewController
{ {
override func collectionView(collectionView: UICollectionView, didHighlightItemAtIndexPath indexPath: NSIndexPath) override func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath)
{ {
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath) self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
} }
override func collectionView(collectionView: UICollectionView, didUnhighlightItemAtIndexPath indexPath: NSIndexPath) override func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath)
{ {
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath) self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
} }
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{ {
self.previousIndexPath = indexPath self.previousIndexPath = indexPath
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath) self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
let pauseItem = self.items[indexPath.item] let pauseItem = self.items[(indexPath as NSIndexPath).item]
pauseItem.action(pauseItem) pauseItem.action(pauseItem)
} }
} }

View File

@ -17,7 +17,7 @@ class PauseViewController: UIViewController, PauseInfoProvidable
var pauseText: String? = nil var pauseText: String? = nil
private weak var saveStatesViewControllerDelegate: SaveStatesViewControllerDelegate? private weak var saveStatesViewControllerDelegate: SaveStatesViewControllerDelegate?
private var saveStatesViewControllerMode = SaveStatesViewController.Mode.Saving private var saveStatesViewControllerMode = SaveStatesViewController.Mode.saving
private weak var cheatsViewControllerDelegate: CheatsViewControllerDelegate? private weak var cheatsViewControllerDelegate: CheatsViewControllerDelegate?
@ -26,7 +26,7 @@ class PauseViewController: UIViewController, PauseInfoProvidable
set { } set { }
get get
{ {
var preferredContentSize = self.pauseNavigationController.topViewController?.preferredContentSize ?? CGSizeZero var preferredContentSize = self.pauseNavigationController.topViewController?.preferredContentSize ?? CGSize.zero
if preferredContentSize.height > 0 if preferredContentSize.height > 0
{ {
preferredContentSize.height += self.pauseNavigationController.navigationBar.bounds.height preferredContentSize.height += self.pauseNavigationController.navigationBar.bounds.height
@ -57,7 +57,7 @@ extension PauseViewController
override func preferredStatusBarStyle() -> UIStatusBarStyle override func preferredStatusBarStyle() -> UIStatusBarStyle
{ {
return .LightContent return .lightContent
} }
override func viewDidLayoutSubviews() override func viewDidLayoutSubviews()
@ -68,11 +68,11 @@ extension PauseViewController
self.pauseNavigationController.navigationBar.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.pauseNavigationController.navigationBar.bounds.height) self.pauseNavigationController.navigationBar.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.pauseNavigationController.navigationBar.bounds.height)
} }
override func targetViewControllerForAction(action: Selector, sender: AnyObject?) -> UIViewController? { override func targetViewController(forAction action: Selector, sender: AnyObject?) -> UIViewController? {
return self.pauseNavigationController return self.pauseNavigationController
} }
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
{ {
switch segue.identifier ?? "" switch segue.identifier ?? ""
{ {
@ -80,7 +80,7 @@ extension PauseViewController
self.pauseNavigationController = segue.destinationViewController as! UINavigationController self.pauseNavigationController = segue.destinationViewController as! UINavigationController
self.pauseNavigationController.delegate = self self.pauseNavigationController.delegate = self
self.pauseNavigationController.navigationBar.tintColor = UIColor.deltaLightPurpleColor() self.pauseNavigationController.navigationBar.tintColor = UIColor.deltaLightPurpleColor()
self.pauseNavigationController.view.backgroundColor = UIColor.clearColor() self.pauseNavigationController.view.backgroundColor = UIColor.clear()
let pauseMenuViewController = self.pauseNavigationController.topViewController as! PauseMenuViewController let pauseMenuViewController = self.pauseNavigationController.topViewController as! PauseMenuViewController
pauseMenuViewController.items = self.items pauseMenuViewController.items = self.items
@ -106,31 +106,31 @@ extension PauseViewController
{ {
func dismiss() func dismiss()
{ {
self.performSegueWithIdentifier("unwindFromPauseMenu", sender: self) self.performSegue(withIdentifier: "unwindFromPauseMenu", sender: self)
} }
func presentSaveStateViewControllerWithMode(mode: SaveStatesViewController.Mode, delegate: SaveStatesViewControllerDelegate) func presentSaveStateViewControllerWithMode(_ mode: SaveStatesViewController.Mode, delegate: SaveStatesViewControllerDelegate)
{ {
self.saveStatesViewControllerMode = mode self.saveStatesViewControllerMode = mode
self.saveStatesViewControllerDelegate = delegate self.saveStatesViewControllerDelegate = delegate
self.performSegueWithIdentifier("saveStates", sender: self) self.performSegue(withIdentifier: "saveStates", sender: self)
} }
func presentCheatsViewController(delegate delegate: CheatsViewControllerDelegate) func presentCheatsViewController(delegate: CheatsViewControllerDelegate)
{ {
self.cheatsViewControllerDelegate = delegate self.cheatsViewControllerDelegate = delegate
self.performSegueWithIdentifier("cheats", sender: self) self.performSegue(withIdentifier: "cheats", sender: self)
} }
} }
extension PauseViewController: UINavigationControllerDelegate extension PauseViewController: UINavigationControllerDelegate
{ {
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?
{ {
let transitionCoordinator = PauseTransitionCoordinator(presentationController: self.presentationController!) let transitionCoordinator = PauseTransitionCoordinator(presentationController: self.presentationController!)
transitionCoordinator.presenting = (operation == .Push) transitionCoordinator.presenting = (operation == .push)
return transitionCoordinator return transitionCoordinator
} }
} }

View File

@ -25,14 +25,14 @@ class PausePresentationController: UIPresentationController
@IBOutlet private weak var pauseIconImageView: UIImageView! @IBOutlet private weak var pauseIconImageView: UIImageView!
@IBOutlet private weak var stackView: UIStackView! @IBOutlet private weak var stackView: UIStackView!
override init(presentedViewController: UIViewController, presentingViewController: UIViewController) override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?)
{ {
self.blurringView = UIVisualEffectView(effect: nil) self.blurringView = UIVisualEffectView(effect: nil)
self.vibrancyView = UIVisualEffectView(effect: nil) self.vibrancyView = UIVisualEffectView(effect: nil)
super.init(presentedViewController: presentedViewController, presentingViewController: presentingViewController) super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
self.contentView = NSBundle.mainBundle().loadNibNamed("PausePresentationControllerContentView", owner: self, options: nil).first as! UIView self.contentView = Bundle.main.loadNibNamed("PausePresentationControllerContentView", owner: self, options: nil).first as! UIView
} }
override func frameOfPresentedViewInContainerView() -> CGRect override func frameOfPresentedViewInContainerView() -> CGRect
@ -44,7 +44,7 @@ class PausePresentationController: UIPresentationController
if contentHeight == 0 if contentHeight == 0
{ {
let statusBarHeight = UIApplication.sharedApplication().statusBarFrame.height let statusBarHeight = UIApplication.shared().statusBarFrame.height
frame = CGRect(x: 0, y: statusBarHeight, width: containerView.bounds.width, height: containerView.bounds.height - statusBarHeight) frame = CGRect(x: 0, y: statusBarHeight, width: containerView.bounds.width, height: containerView.bounds.height - statusBarHeight)
} }
else else
@ -71,22 +71,22 @@ class PausePresentationController: UIPresentationController
} }
self.blurringView.frame = self.containerView!.frame self.blurringView.frame = self.containerView!.frame
self.blurringView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] self.blurringView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.containerView?.addSubview(self.blurringView) self.containerView?.addSubview(self.blurringView)
self.vibrancyView.frame = self.containerView!.frame self.vibrancyView.frame = self.containerView!.frame
self.vibrancyView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] self.vibrancyView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.containerView?.addSubview(self.vibrancyView) self.containerView?.addSubview(self.vibrancyView)
self.contentView.alpha = 0.0 self.contentView.alpha = 0.0
self.vibrancyView.contentView.addSubview(self.contentView) self.vibrancyView.contentView.addSubview(self.contentView)
self.presentingViewController.transitionCoordinator()?.animateAlongsideTransition({ context in self.presentingViewController.transitionCoordinator()?.animate(alongsideTransition: { context in
let blurEffect = UIBlurEffect(style: .Dark) let blurEffect = UIBlurEffect(style: .dark)
self.blurringView.effect = blurEffect self.blurringView.effect = blurEffect
self.vibrancyView.effect = UIVibrancyEffect(forBlurEffect: blurEffect) self.vibrancyView.effect = UIVibrancyEffect(blurEffect: blurEffect)
self.contentView.alpha = 1.0 self.contentView.alpha = 1.0
@ -95,22 +95,22 @@ class PausePresentationController: UIPresentationController
override func dismissalTransitionWillBegin() override func dismissalTransitionWillBegin()
{ {
self.presentingViewController.transitionCoordinator()?.animateAlongsideTransition({ context in self.presentingViewController.transitionCoordinator()?.animate(alongsideTransition: { context in
self.blurringView.effect = nil self.blurringView.effect = nil
self.vibrancyView.effect = nil self.vibrancyView.effect = nil
self.contentView.alpha = 0.0 self.contentView.alpha = 0.0
}, completion: nil) }, completion: nil)
} }
override func dismissalTransitionDidEnd(completed: Bool) override func dismissalTransitionDidEnd(_ completed: Bool)
{ {
self.blurringView.removeFromSuperview() self.blurringView.removeFromSuperview()
self.vibrancyView.removeFromSuperview() self.vibrancyView.removeFromSuperview()
} }
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
{ {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) super.viewWillTransition(to: size, with: coordinator)
// Super super hacky, but the system for some reason tries to layout the view in a (slightly) smaller space, which sometimes breaks constraints // Super super hacky, but the system for some reason tries to layout the view in a (slightly) smaller space, which sometimes breaks constraints
// To fix this, we ensure there is enough room for the constraints to be valid temporarily, and then the frame will be fixed in containerViewDidLayoutSubviews() // To fix this, we ensure there is enough room for the constraints to be valid temporarily, and then the frame will be fixed in containerViewDidLayoutSubviews()
@ -141,7 +141,7 @@ class PausePresentationController: UIPresentationController
self.contentView.removeFromSuperview() self.contentView.removeFromSuperview()
// Temporarily match the bounds of self.containerView (accounting for the status bar) // Temporarily match the bounds of self.containerView (accounting for the status bar)
let statusBarHeight = UIApplication.sharedApplication().statusBarFrame.height let statusBarHeight = UIApplication.shared().statusBarFrame.height
self.contentView.frame = CGRect(x: 0, y: statusBarHeight, width: self.containerView!.bounds.width, height: self.containerView!.bounds.height - statusBarHeight) self.contentView.frame = CGRect(x: 0, y: statusBarHeight, width: self.containerView!.bounds.width, height: self.containerView!.bounds.height - statusBarHeight)
// Layout content view // Layout content view
@ -163,7 +163,7 @@ class PausePresentationController: UIPresentationController
self.presentedView()?.frame = self.frameOfPresentedViewInContainerView() self.presentedView()?.frame = self.frameOfPresentedViewInContainerView()
// Unhide pauseIconImageView so its height is involved with layout calculations // Unhide pauseIconImageView so its height is involved with layout calculations
self.pauseIconImageView.hidden = false self.pauseIconImageView.isHidden = false
self.contentView.frame = CGRect(x: 0, y: statusBarHeight, width: self.containerView!.bounds.width, height: self.frameOfPresentedViewInContainerView().minY - statusBarHeight) self.contentView.frame = CGRect(x: 0, y: statusBarHeight, width: self.containerView!.bounds.width, height: self.frameOfPresentedViewInContainerView().minY - statusBarHeight)
@ -173,11 +173,11 @@ class PausePresentationController: UIPresentationController
let currentScaleFactor = self.pauseLabel.currentScaleFactor let currentScaleFactor = self.pauseLabel.currentScaleFactor
if currentScaleFactor < self.pauseLabel.minimumScaleFactor || CGFloatEqualToFloat(currentScaleFactor, self.pauseLabel.minimumScaleFactor) if currentScaleFactor < self.pauseLabel.minimumScaleFactor || CGFloatEqualToFloat(currentScaleFactor, self.pauseLabel.minimumScaleFactor)
{ {
self.pauseIconImageView.hidden = true self.pauseIconImageView.isHidden = true
} }
else else
{ {
self.pauseIconImageView.hidden = false self.pauseIconImageView.isHidden = false
} }
self.contentView.setNeedsLayout() // Ensures that layout will actually occur (sometimes the system thinks a layout is not needed, which messes up calculations) self.contentView.setNeedsLayout() // Ensures that layout will actually occur (sometimes the system thinks a layout is not needed, which messes up calculations)

View File

@ -29,17 +29,17 @@ class SaveStatesCollectionHeaderView: UICollectionReusableView
private func initialize() private func initialize()
{ {
self.textLabel.translatesAutoresizingMaskIntoConstraints = false self.textLabel.translatesAutoresizingMaskIntoConstraints = false
self.textLabel.textColor = UIColor.whiteColor() self.textLabel.textColor = UIColor.white()
var fontDescriptor = UIFontDescriptor.preferredFontDescriptorWithTextStyle(UIFontTextStyleTitle3) var fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: UIFontTextStyleTitle3)
fontDescriptor = fontDescriptor.fontDescriptorWithSymbolicTraits([.TraitBold]) fontDescriptor = fontDescriptor.withSymbolicTraits([.traitBold])!
self.textLabel.font = UIFont(descriptor: fontDescriptor, size: 0.0) self.textLabel.font = UIFont(descriptor: fontDescriptor, size: 0.0)
self.textLabel.textAlignment = .Center self.textLabel.textAlignment = .center
self.addSubview(self.textLabel) self.addSubview(self.textLabel)
// Auto Layout // Auto Layout
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[textLabel]-20-|", options: [], metrics: nil, views: ["textLabel": self.textLabel])) NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "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])) NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[textLabel]|", options: [], metrics: nil, views: ["textLabel": self.textLabel]))
} }
} }

View File

@ -14,24 +14,24 @@ import Roxas
protocol SaveStatesViewControllerDelegate: class protocol SaveStatesViewControllerDelegate: class
{ {
func saveStatesViewControllerActiveEmulatorCore(saveStatesViewController: SaveStatesViewController) -> EmulatorCore func saveStatesViewControllerActiveEmulatorCore(_ saveStatesViewController: SaveStatesViewController) -> EmulatorCore
func saveStatesViewController(saveStatesViewController: SaveStatesViewController, updateSaveState saveState: SaveState) func saveStatesViewController(_ saveStatesViewController: SaveStatesViewController, updateSaveState saveState: SaveState)
func saveStatesViewController(saveStatesViewController: SaveStatesViewController, loadSaveState saveState: SaveStateType) func saveStatesViewController(_ saveStatesViewController: SaveStatesViewController, loadSaveState saveState: SaveStateType)
} }
extension SaveStatesViewController extension SaveStatesViewController
{ {
enum Mode enum Mode
{ {
case Saving case saving
case Loading case loading
} }
enum Section: Int enum Section: Int
{ {
case Auto case auto
case General case general
case Locked case locked
} }
} }
@ -43,7 +43,7 @@ class SaveStatesViewController: UICollectionViewController
} }
} }
var mode = Mode.Saving var mode = Mode.saving
private var backgroundView: RSTBackgroundView! private var backgroundView: RSTBackgroundView!
@ -51,21 +51,21 @@ class SaveStatesViewController: UICollectionViewController
private var prototypeCellWidthConstraint: NSLayoutConstraint! private var prototypeCellWidthConstraint: NSLayoutConstraint!
private var prototypeHeader = SaveStatesCollectionHeaderView() private var prototypeHeader = SaveStatesCollectionHeaderView()
private var fetchedResultsController: NSFetchedResultsController! private var fetchedResultsController: NSFetchedResultsController<AnyObject>!
private let imageOperationQueue = RSTOperationQueue() private let imageOperationQueue = RSTOperationQueue()
private let imageCache = NSCache() private let imageCache = Cache()
private var currentGameState: SaveStateType? private var currentGameState: SaveStateType?
private var selectedSaveState: SaveState? private var selectedSaveState: SaveState?
private let dateFormatter: NSDateFormatter private let dateFormatter: DateFormatter
required init?(coder aDecoder: NSCoder) required init?(coder aDecoder: NSCoder)
{ {
self.dateFormatter = NSDateFormatter() self.dateFormatter = DateFormatter()
self.dateFormatter.timeStyle = .ShortStyle self.dateFormatter.timeStyle = .short
self.dateFormatter.dateStyle = .ShortStyle self.dateFormatter.dateStyle = .short
super.init(coder: aDecoder) super.init(coder: aDecoder)
} }
@ -78,16 +78,16 @@ extension SaveStatesViewController
super.viewDidLoad() super.viewDidLoad()
self.backgroundView = RSTBackgroundView(frame: self.view.bounds) self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
self.backgroundView.hidden = true self.backgroundView.isHidden = true
self.backgroundView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] self.backgroundView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.backgroundView.textLabel.text = NSLocalizedString("No Save States", comment: "") self.backgroundView.textLabel.text = NSLocalizedString("No Save States", comment: "")
self.backgroundView.textLabel.textColor = UIColor.whiteColor() self.backgroundView.textLabel.textColor = UIColor.white()
self.backgroundView.detailTextLabel.textColor = UIColor.whiteColor() self.backgroundView.detailTextLabel.textColor = UIColor.white()
self.view.insertSubview(self.backgroundView, atIndex: 0) self.view.insertSubview(self.backgroundView, at: 0)
let collectionViewLayout = self.collectionViewLayout as! GridCollectionViewLayout let collectionViewLayout = self.collectionViewLayout as! GridCollectionViewLayout
let averageHorizontalInset = (collectionViewLayout.sectionInset.left + collectionViewLayout.sectionInset.right) / 2 let averageHorizontalInset = (collectionViewLayout.sectionInset.left + collectionViewLayout.sectionInset.right) / 2
let portraitScreenWidth = UIScreen.mainScreen().coordinateSpace.convertRect(UIScreen.mainScreen().bounds, toCoordinateSpace: UIScreen.mainScreen().fixedCoordinateSpace).width let portraitScreenWidth = UIScreen.main().coordinateSpace.convert(UIScreen.main().bounds, to: UIScreen.main().fixedCoordinateSpace).width
// Use dimensions that allow two cells to fill the screen horizontally with padding in portrait mode // Use dimensions that allow two cells to fill the screen horizontally with padding in portrait mode
// We'll keep the same size for landscape orientation, which will allow more to fit // We'll keep the same size for landscape orientation, which will allow more to fit
@ -95,29 +95,29 @@ extension SaveStatesViewController
switch self.mode switch self.mode
{ {
case .Saving: case .saving:
self.title = NSLocalizedString("Save State", comment: "") self.title = NSLocalizedString("Save State", comment: "")
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can create a new save state by pressing the + button in the top right.", comment: "") self.backgroundView.detailTextLabel.text = NSLocalizedString("You can create a new save state by pressing the + button in the top right.", comment: "")
case .Loading: case .loading:
self.title = NSLocalizedString("Load State", comment: "") self.title = NSLocalizedString("Load State", comment: "")
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can create a new save state by pressing the Save State option in the pause menu.", comment: "") self.backgroundView.detailTextLabel.text = NSLocalizedString("You can create a new save state by pressing the Save State option in the pause menu.", comment: "")
self.navigationItem.rightBarButtonItem = nil self.navigationItem.rightBarButtonItem = nil
} }
// Manually update prototype cell properties // Manually update prototype cell properties
self.prototypeCellWidthConstraint = self.prototypeCell.contentView.widthAnchor.constraintEqualToConstant(collectionViewLayout.itemWidth) self.prototypeCellWidthConstraint = self.prototypeCell.contentView.widthAnchor.constraint(equalToConstant: collectionViewLayout.itemWidth)
self.prototypeCellWidthConstraint.active = true self.prototypeCellWidthConstraint.isActive = true
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(SaveStatesViewController.handleLongPressGesture(_:))) let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(SaveStatesViewController.handleLongPressGesture(_:)))
self.collectionView?.addGestureRecognizer(longPressGestureRecognizer) self.collectionView?.addGestureRecognizer(longPressGestureRecognizer)
self.registerForPreviewingWithDelegate(self, sourceView: self.collectionView!) self.registerForPreviewing(with: self, sourceView: self.collectionView!)
self.updateBackgroundView() self.updateBackgroundView()
} }
override func viewWillAppear(animated: Bool) override func viewWillAppear(_ animated: Bool)
{ {
self.fetchedResultsController.performFetchIfNeeded() self.fetchedResultsController.performFetchIfNeeded()
@ -126,7 +126,7 @@ extension SaveStatesViewController
super.viewWillAppear(animated) super.viewWillAppear(animated)
} }
override func viewDidDisappear(animated: Bool) override func viewDidDisappear(_ animated: Bool)
{ {
super.viewDidDisappear(animated) super.viewDidDisappear(animated)
@ -149,8 +149,8 @@ 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 = Predicate(format: "%K == %@", SaveState.Attributes.game.rawValue, game)
fetchRequest.sortDescriptors = [NSSortDescriptor(key: SaveState.Attributes.type.rawValue, ascending: true), NSSortDescriptor(key: SaveState.Attributes.creationDate.rawValue, ascending: true)] fetchRequest.sortDescriptors = [SortDescriptor(key: SaveState.Attributes.type.rawValue, ascending: true), SortDescriptor(key: SaveState.Attributes.creationDate.rawValue, ascending: true)]
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: SaveState.Attributes.type.rawValue, 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
@ -160,21 +160,21 @@ private extension SaveStatesViewController
{ {
if let fetchedObjects = self.fetchedResultsController.fetchedObjects where fetchedObjects.count > 0 if let fetchedObjects = self.fetchedResultsController.fetchedObjects where fetchedObjects.count > 0
{ {
self.backgroundView.hidden = true self.backgroundView.isHidden = true
} }
else else
{ {
self.backgroundView.hidden = false self.backgroundView.isHidden = false
} }
} }
//MARK: - Configure Views - //MARK: - Configure Views -
func configureCollectionViewCell(cell: GridCollectionViewCell, forIndexPath indexPath: NSIndexPath, ignoreExpensiveOperations ignoreOperations: Bool = false) func configureCollectionViewCell(_ cell: GridCollectionViewCell, forIndexPath indexPath: IndexPath, ignoreExpensiveOperations ignoreOperations: Bool = false)
{ {
let saveState = self.fetchedResultsController.objectAtIndexPath(indexPath) as! SaveState let saveState = self.fetchedResultsController.object(at: indexPath) as! SaveState
cell.imageView.backgroundColor = UIColor.whiteColor() cell.imageView.backgroundColor = UIColor.white()
cell.imageView.image = UIImage(named: "DeltaPlaceholder") cell.imageView.image = UIImage(named: "DeltaPlaceholder")
if !ignoreOperations if !ignoreOperations
@ -191,25 +191,25 @@ private extension SaveStatesViewController
} }
// Ensure initially visible cells have loaded their image before they appear to prevent potential flickering from placeholder to thumbnail // Ensure initially visible cells have loaded their image before they appear to prevent potential flickering from placeholder to thumbnail
if self.appearing if self.isAppearing
{ {
imageOperation.immediate = true imageOperation.isImmediate = true
} }
self.imageOperationQueue.addOperation(imageOperation, forKey: indexPath) self.imageOperationQueue.addOperation(imageOperation, forKey: indexPath)
} }
let dimensions = self.delegate.saveStatesViewControllerActiveEmulatorCore(self).preferredRenderingSize let dimensions = self.delegate.saveStatesViewControllerActiveEmulatorCore(self).preferredRenderingSize
cell.maximumImageSize = CGSizeMake(self.prototypeCellWidthConstraint.constant, (self.prototypeCellWidthConstraint.constant / dimensions.width) * dimensions.height) cell.maximumImageSize = CGSize(width: self.prototypeCellWidthConstraint.constant, height: (self.prototypeCellWidthConstraint.constant / dimensions.width) * dimensions.height)
cell.textLabel.textColor = UIColor.whiteColor() cell.textLabel.textColor = UIColor.white()
cell.textLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline) cell.textLabel.font = UIFont.preferredFont(forTextStyle: UIFontTextStyleSubheadline)
let name = saveState.name ?? self.dateFormatter.stringFromDate(saveState.modifiedDate) let name = saveState.name ?? self.dateFormatter.string(from: saveState.modifiedDate)
cell.textLabel.text = name cell.textLabel.text = name
} }
func configureCollectionViewHeaderView(headerView: SaveStatesCollectionHeaderView, forSection section: Int) func configureCollectionViewHeaderView(_ headerView: SaveStatesCollectionHeaderView, forSection section: Int)
{ {
let section = self.correctedSectionForSectionIndex(section) let section = self.correctedSectionForSectionIndex(section)
@ -217,9 +217,9 @@ private extension SaveStatesViewController
switch section switch section
{ {
case .Auto: title = NSLocalizedString("Auto Save", comment: "") case .auto: title = NSLocalizedString("Auto Save", comment: "")
case .General: title = NSLocalizedString("General", comment: "") case .general: title = NSLocalizedString("General", comment: "")
case .Locked: title = NSLocalizedString("Locked", comment: "") case .locked: title = NSLocalizedString("Locked", comment: "")
} }
headerView.textLabel.text = title headerView.textLabel.text = title
@ -227,15 +227,15 @@ private extension SaveStatesViewController
//MARK: - Gestures - //MARK: - Gestures -
@objc func handleLongPressGesture(gestureRecognizer: UILongPressGestureRecognizer) @objc func handleLongPressGesture(_ gestureRecognizer: UILongPressGestureRecognizer)
{ {
guard gestureRecognizer.state == .Began else { return } guard gestureRecognizer.state == .began else { return }
guard let indexPath = self.collectionView?.indexPathForItemAtPoint(gestureRecognizer.locationInView(self.collectionView)) else { return } guard let indexPath = self.collectionView?.indexPathForItem(at: gestureRecognizer.location(in: self.collectionView)) else { return }
let saveState = self.fetchedResultsController.objectAtIndexPath(indexPath) as! SaveState let saveState = self.fetchedResultsController.object(at: indexPath) as! SaveState
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet) let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let actions = self.actionsForSaveState(saveState).map { $0.alertAction } let actions = self.actionsForSaveState(saveState).map { $0.alertAction }
for action in actions for action in actions
@ -243,7 +243,7 @@ private extension SaveStatesViewController
alertController.addAction(action) alertController.addAction(action)
} }
self.presentViewController(alertController, animated: true, completion: nil) self.present(alertController, animated: true, completion: nil)
} }
//MARK: - Save States - //MARK: - Save States -
@ -251,10 +251,10 @@ private extension SaveStatesViewController
@IBAction func addSaveState() @IBAction func addSaveState()
{ {
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext() let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlock { backgroundContext.perform {
var game = self.delegate.saveStatesViewControllerActiveEmulatorCore(self).game as! Game var game = self.delegate.saveStatesViewControllerActiveEmulatorCore(self).game as! Game
game = backgroundContext.objectWithID(game.objectID) as! Game game = backgroundContext.object(with: game.objectID) as! Game
let saveState = SaveState.insertIntoManagedObjectContext(backgroundContext) let saveState = SaveState.insertIntoManagedObjectContext(backgroundContext)
saveState.game = game saveState.game = game
@ -263,17 +263,17 @@ private extension SaveStatesViewController
} }
} }
func updateSaveState(saveState: SaveState) func updateSaveState(_ saveState: SaveState)
{ {
self.delegate?.saveStatesViewController(self, updateSaveState: saveState) self.delegate?.saveStatesViewController(self, updateSaveState: saveState)
saveState.managedObjectContext?.saveWithErrorLogging() saveState.managedObjectContext?.saveWithErrorLogging()
} }
func loadSaveState(saveState: SaveState) func loadSaveState(_ saveState: SaveState)
{ {
let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self) let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self)
if emulatorCore.state == .Stopped if emulatorCore.state == .stopped
{ {
emulatorCore.startEmulation() emulatorCore.startEmulation()
emulatorCore.pauseEmulation() emulatorCore.pauseEmulation()
@ -282,47 +282,47 @@ private extension SaveStatesViewController
self.delegate?.saveStatesViewController(self, loadSaveState: saveState) self.delegate?.saveStatesViewController(self, loadSaveState: saveState)
} }
func deleteSaveState(saveState: SaveState) func deleteSaveState(_ saveState: SaveState)
{ {
let confirmationAlertController = UIAlertController(title: NSLocalizedString("Delete Save State?", comment: ""), message: NSLocalizedString("Are you sure you want to delete this save state? This cannot be undone.", comment: ""), preferredStyle: .Alert) let confirmationAlertController = UIAlertController(title: NSLocalizedString("Delete Save State?", comment: ""), message: NSLocalizedString("Are you sure you want to delete this save state? This cannot be undone.", comment: ""), preferredStyle: .alert)
confirmationAlertController.addAction(UIAlertAction(title: NSLocalizedString("Delete", comment: ""), style: .Default, handler: { action in confirmationAlertController.addAction(UIAlertAction(title: NSLocalizedString("Delete", comment: ""), style: .default, handler: { action in
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext() let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlock { backgroundContext.perform {
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID) let temporarySaveState = backgroundContext.object(with: saveState.objectID)
backgroundContext.deleteObject(temporarySaveState) backgroundContext.delete(temporarySaveState)
backgroundContext.saveWithErrorLogging() backgroundContext.saveWithErrorLogging()
} }
})) }))
confirmationAlertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil)) confirmationAlertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil))
self.presentViewController(confirmationAlertController, animated: true, completion: nil) self.present(confirmationAlertController, animated: true, completion: nil)
} }
func renameSaveState(saveState: SaveState) func renameSaveState(_ saveState: SaveState)
{ {
self.selectedSaveState = saveState self.selectedSaveState = saveState
let alertController = UIAlertController(title: NSLocalizedString("Rename Save State", comment: ""), message: nil, preferredStyle: .Alert) let alertController = UIAlertController(title: NSLocalizedString("Rename Save State", comment: ""), message: nil, preferredStyle: .alert)
alertController.addTextFieldWithConfigurationHandler { (textField) in alertController.addTextField { (textField) in
textField.text = saveState.name textField.text = saveState.name
textField.placeholder = NSLocalizedString("Name", comment: "") textField.placeholder = NSLocalizedString("Name", comment: "")
textField.autocapitalizationType = .Words textField.autocapitalizationType = .words
textField.returnKeyType = .Done textField.returnKeyType = .done
textField.addTarget(self, action: #selector(SaveStatesViewController.updateSaveStateName(_:)), forControlEvents: .EditingDidEnd) textField.addTarget(self, action: #selector(SaveStatesViewController.updateSaveStateName(_:)), for: .editingDidEnd)
} }
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: { (action) in alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: { (action) in
self.selectedSaveState = nil self.selectedSaveState = nil
})) }))
alertController.addAction(UIAlertAction(title: NSLocalizedString("Rename", comment: ""), style: .Default, handler: { (action) in alertController.addAction(UIAlertAction(title: NSLocalizedString("Rename", comment: ""), style: .default, handler: { (action) in
self.updateSaveStateName(alertController.textFields!.first!) self.updateSaveStateName(alertController.textFields!.first!)
})) }))
self.presentViewController(alertController, animated: true, completion: nil) self.present(alertController, animated: true, completion: nil)
} }
@objc func updateSaveStateName(textField: UITextField) @objc func updateSaveStateName(_ textField: UITextField)
{ {
guard let selectedSaveState = self.selectedSaveState else { return } guard let selectedSaveState = self.selectedSaveState else { return }
@ -334,9 +334,9 @@ private extension SaveStatesViewController
} }
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext() let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlock { backgroundContext.perform {
let saveState = backgroundContext.objectWithID(selectedSaveState.objectID) as! SaveState let saveState = backgroundContext.object(with: selectedSaveState.objectID) as! SaveState
saveState.name = text saveState.name = text
backgroundContext.saveWithErrorLogging() backgroundContext.saveWithErrorLogging()
@ -345,21 +345,21 @@ private extension SaveStatesViewController
self.selectedSaveState = nil self.selectedSaveState = nil
} }
func updatePreviewSaveState(saveState: SaveState?) func updatePreviewSaveState(_ saveState: SaveState?)
{ {
let alertController = UIAlertController(title: NSLocalizedString("Change Preview Save State?", comment: ""), message: NSLocalizedString("The Preview Save State is loaded whenever you preview this game from the Main Menu with 3D Touch. Are you sure you want to change it?", comment: ""), preferredStyle: .Alert) let alertController = UIAlertController(title: NSLocalizedString("Change Preview Save State?", comment: ""), message: NSLocalizedString("The Preview Save State is loaded whenever you preview this game from the Main Menu with 3D Touch. Are you sure you want to change it?", comment: ""), preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil)) alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil))
alertController.addAction(UIAlertAction(title: NSLocalizedString("Change", comment: ""), style: .Default, handler: { (action) in alertController.addAction(UIAlertAction(title: NSLocalizedString("Change", comment: ""), style: .default, handler: { (action) in
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext() let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlock { backgroundContext.perform {
var game = self.delegate.saveStatesViewControllerActiveEmulatorCore(self).game as! Game var game = self.delegate.saveStatesViewControllerActiveEmulatorCore(self).game as! Game
game = backgroundContext.objectWithID(game.objectID) as! Game game = backgroundContext.object(with: game.objectID) as! Game
if let saveState = saveState if let saveState = saveState
{ {
let previewSaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState let previewSaveState = backgroundContext.object(with: saveState.objectID) as! SaveState
game.previewSaveState = previewSaveState game.previewSaveState = previewSaveState
} }
else else
@ -372,25 +372,25 @@ private extension SaveStatesViewController
})) }))
self.presentViewController(alertController, animated: true, completion: nil) self.present(alertController, animated: true, completion: nil)
} }
func lockSaveState(saveState: SaveState) func lockSaveState(_ saveState: SaveState)
{ {
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext() let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlockAndWait() { backgroundContext.performAndWait() {
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState let temporarySaveState = backgroundContext.object(with: saveState.objectID) as! SaveState
temporarySaveState.type = .Locked temporarySaveState.type = .locked
backgroundContext.saveWithErrorLogging() backgroundContext.saveWithErrorLogging()
} }
} }
func unlockSaveState(saveState: SaveState) func unlockSaveState(_ saveState: SaveState)
{ {
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext() let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlockAndWait() { backgroundContext.performAndWait() {
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState let temporarySaveState = backgroundContext.object(with: saveState.objectID) as! SaveState
temporarySaveState.type = .General temporarySaveState.type = .general
backgroundContext.saveWithErrorLogging() backgroundContext.saveWithErrorLogging()
} }
} }
@ -406,7 +406,7 @@ private extension SaveStatesViewController
// Remove temporary save state file // Remove temporary save state file
do do
{ {
try NSFileManager.defaultManager().removeItemAtURL(saveState.fileURL) try FileManager.default.removeItem(at: saveState.fileURL)
} }
catch let error as NSError catch let error as NSError
{ {
@ -447,7 +447,7 @@ private extension SaveStatesViewController
//MARK: - Convenience Methods - //MARK: - Convenience Methods -
func correctedSectionForSectionIndex(section: Int) -> Section func correctedSectionForSectionIndex(_ section: Int) -> Section
{ {
let sectionInfo = self.fetchedResultsController.sections![section] let sectionInfo = self.fetchedResultsController.sections![section]
let sectionIndex = Int(sectionInfo.name)! let sectionIndex = Int(sectionInfo.name)!
@ -456,53 +456,53 @@ private extension SaveStatesViewController
return section return section
} }
func actionsForSaveState(saveState: SaveState) -> [Action] func actionsForSaveState(_ saveState: SaveState) -> [Action]
{ {
var actions = [Action]() var actions = [Action]()
if self.traitCollection.forceTouchCapability == .Available if self.traitCollection.forceTouchCapability == .available
{ {
if saveState.game.previewSaveState != saveState if saveState.game.previewSaveState != saveState
{ {
let previewAction = Action(title: NSLocalizedString("Set as Preview Save State", comment: ""), style: .Default, action: { action in let previewAction = Action(title: NSLocalizedString("Set as Preview Save State", comment: ""), style: .default, action: { action in
self.updatePreviewSaveState(saveState) self.updatePreviewSaveState(saveState)
}) })
actions.append(previewAction) actions.append(previewAction)
} }
else else
{ {
let previewAction = Action(title: NSLocalizedString("Remove as Preview Save State", comment: ""), style: .Default, action: { action in let previewAction = Action(title: NSLocalizedString("Remove as Preview Save State", comment: ""), style: .default, action: { action in
self.updatePreviewSaveState(nil) self.updatePreviewSaveState(nil)
}) })
actions.append(previewAction) actions.append(previewAction)
} }
} }
let cancelAction = Action(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, action: nil) let cancelAction = Action(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, action: nil)
actions.append(cancelAction) actions.append(cancelAction)
let renameAction = Action(title: NSLocalizedString("Rename", comment: ""), style: .Default, action: { action in let renameAction = Action(title: NSLocalizedString("Rename", comment: ""), style: .default, action: { action in
self.renameSaveState(saveState) self.renameSaveState(saveState)
}) })
actions.append(renameAction) actions.append(renameAction)
switch saveState.type switch saveState.type
{ {
case .Auto: break case .auto: break
case .General: case .general:
let lockAction = Action(title: NSLocalizedString("Lock", comment: ""), style: .Default, action: { action in let lockAction = Action(title: NSLocalizedString("Lock", comment: ""), style: .default, action: { action in
self.lockSaveState(saveState) self.lockSaveState(saveState)
}) })
actions.append(lockAction) actions.append(lockAction)
case .Locked: case .locked:
let unlockAction = Action(title: NSLocalizedString("Unlock", comment: ""), style: .Default, action: { action in let unlockAction = Action(title: NSLocalizedString("Unlock", comment: ""), style: .default, action: { action in
self.unlockSaveState(saveState) self.unlockSaveState(saveState)
}) })
actions.append(unlockAction) actions.append(unlockAction)
} }
let deleteAction = Action(title: NSLocalizedString("Delete", comment: ""), style: .Destructive, action: { action in let deleteAction = Action(title: NSLocalizedString("Delete", comment: ""), style: .destructive, action: { action in
self.deleteSaveState(saveState) self.deleteSaveState(saveState)
}) })
actions.append(deleteAction) actions.append(deleteAction)
@ -514,20 +514,20 @@ private extension SaveStatesViewController
//MARK: - <UIViewControllerPreviewingDelegate> - //MARK: - <UIViewControllerPreviewingDelegate> -
extension SaveStatesViewController: UIViewControllerPreviewingDelegate extension SaveStatesViewController: UIViewControllerPreviewingDelegate
{ {
func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?
{ {
guard let indexPath = self.collectionView?.indexPathForItemAtPoint(location), layoutAttributes = self.collectionViewLayout.layoutAttributesForItemAtIndexPath(indexPath) else { return nil } guard let indexPath = self.collectionView?.indexPathForItem(at: location), layoutAttributes = self.collectionViewLayout.layoutAttributesForItem(at: indexPath) else { return nil }
previewingContext.sourceRect = layoutAttributes.frame previewingContext.sourceRect = layoutAttributes.frame
let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self) let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self)
let storyboard = UIStoryboard(name: "Main", bundle: nil) let storyboard = UIStoryboard(name: "Main", bundle: nil)
let saveState = self.fetchedResultsController.objectAtIndexPath(indexPath) as! SaveState let saveState = self.fetchedResultsController.object(at: indexPath) as! SaveState
let emulationViewController = storyboard.instantiateViewControllerWithIdentifier("emulationViewController") as! EmulationViewController let emulationViewController = storyboard.instantiateViewController(withIdentifier: "emulationViewController") as! EmulationViewController
emulationViewController.game = emulatorCore.game as! Game emulationViewController.game = emulatorCore.game as! Game
emulationViewController.overridePreviewActionItems = self.actionsForSaveState(saveState).filter{ $0.style != .Cancel }.map{ $0.previewAction } emulationViewController.overridePreviewActionItems = self.actionsForSaveState(saveState).filter{ $0.style != .cancel }.map{ $0.previewAction }
emulationViewController.deferredPreparationHandler = { [unowned emulationViewController] in emulationViewController.deferredPreparationHandler = { [unowned emulationViewController] in
// Store reference to current game state before we stop emulation so we can resume it if user decides to not load a save state // Store reference to current game state before we stop emulation so we can resume it if user decides to not load a save state
@ -535,11 +535,11 @@ extension SaveStatesViewController: UIViewControllerPreviewingDelegate
{ {
emulatorCore.saveSaveState() { saveState in emulatorCore.saveSaveState() { saveState in
let fileURL = NSFileManager.uniqueTemporaryURL() let fileURL = FileManager.uniqueTemporaryURL()
do do
{ {
try NSFileManager.defaultManager().moveItemAtURL(saveState.fileURL, toURL: fileURL) try FileManager.default.moveItem(at: saveState.fileURL, to: fileURL)
} }
catch let error as NSError catch let error as NSError
{ {
@ -572,7 +572,7 @@ extension SaveStatesViewController: UIViewControllerPreviewingDelegate
return emulationViewController return emulationViewController
} }
func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController)
{ {
let emulationViewController = viewControllerToCommit as! EmulationViewController let emulationViewController = viewControllerToCommit as! EmulationViewController
@ -598,29 +598,29 @@ extension SaveStatesViewController: UIViewControllerPreviewingDelegate
//MARK: - <UICollectionViewDataSource> - //MARK: - <UICollectionViewDataSource> -
extension SaveStatesViewController extension SaveStatesViewController
{ {
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int override func numberOfSections(in collectionView: UICollectionView) -> Int
{ {
let numberOfSections = self.fetchedResultsController.sections!.count let numberOfSections = self.fetchedResultsController.sections!.count
return numberOfSections 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]
return section.numberOfObjects return section.numberOfObjects
} }
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{ {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(RSTGenericCellIdentifier, forIndexPath: indexPath) as! GridCollectionViewCell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: RSTGenericCellIdentifier, for: indexPath) as! GridCollectionViewCell
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 override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
{ {
let headerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "Header", forIndexPath: indexPath) as! SaveStatesCollectionHeaderView let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Header", for: indexPath) as! SaveStatesCollectionHeaderView
self.configureCollectionViewHeaderView(headerView, forSection: indexPath.section) self.configureCollectionViewHeaderView(headerView, forSection: (indexPath as NSIndexPath).section)
return headerView return headerView
} }
} }
@ -628,39 +628,39 @@ extension SaveStatesViewController
//MARK: - <UICollectionViewDelegate> - //MARK: - <UICollectionViewDelegate> -
extension SaveStatesViewController extension SaveStatesViewController
{ {
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{ {
let saveState = self.fetchedResultsController.objectAtIndexPath(indexPath) as! SaveState let saveState = self.fetchedResultsController.object(at: indexPath) as! SaveState
switch self.mode switch self.mode
{ {
case .Saving: case .saving:
let section = self.correctedSectionForSectionIndex(indexPath.section) let section = self.correctedSectionForSectionIndex((indexPath as NSIndexPath).section)
switch section switch section
{ {
case .Auto: break case .auto: break
case .General: case .general:
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext() let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlockAndWait() { backgroundContext.performAndWait() {
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState let temporarySaveState = backgroundContext.object(with: saveState.objectID) as! SaveState
self.updateSaveState(temporarySaveState) self.updateSaveState(temporarySaveState)
} }
case .Locked: 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) 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)) alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .cancel, handler: nil))
self.presentViewController(alertController, animated: true, completion: nil) self.present(alertController, animated: true, completion: nil)
} }
case .Loading: self.loadSaveState(saveState) case .loading: self.loadSaveState(saveState)
} }
} }
override func collectionView(collectionView: UICollectionView, didEndDisplayingCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) override func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
{ {
let operation = self.imageOperationQueue.operationForKey(indexPath) let operation = self.imageOperationQueue.operation(forKey: indexPath)
operation?.cancel() operation?.cancel()
} }
} }
@ -668,20 +668,20 @@ extension SaveStatesViewController
//MARK: - <UICollectionViewDelegateFlowLayout> - //MARK: - <UICollectionViewDelegateFlowLayout> -
extension SaveStatesViewController: UICollectionViewDelegateFlowLayout extension SaveStatesViewController: UICollectionViewDelegateFlowLayout
{ {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{ {
// No need to load images from disk just to determine size, so we pass true for ignoreExpensiveOperations // No need to load images from disk just to determine size, so we pass true for ignoreExpensiveOperations
self.configureCollectionViewCell(self.prototypeCell, forIndexPath: indexPath, ignoreExpensiveOperations: true) self.configureCollectionViewCell(self.prototypeCell, forIndexPath: indexPath, ignoreExpensiveOperations: true)
let size = self.prototypeCell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize) let size = self.prototypeCell.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
return size return size
} }
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize
{ {
self.configureCollectionViewHeaderView(self.prototypeHeader, forSection: section) self.configureCollectionViewHeaderView(self.prototypeHeader, forSection: section)
let size = self.prototypeHeader.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize) let size = self.prototypeHeader.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
return size return size
} }
} }
@ -689,7 +689,7 @@ extension SaveStatesViewController: UICollectionViewDelegateFlowLayout
//MARK: - <NSFetchedResultsControllerDelegate> - //MARK: - <NSFetchedResultsControllerDelegate> -
extension SaveStatesViewController: NSFetchedResultsControllerDelegate extension SaveStatesViewController: NSFetchedResultsControllerDelegate
{ {
func controllerDidChangeContent(controller: NSFetchedResultsController) func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
{ {
self.collectionView?.reloadData() self.collectionView?.reloadData()
self.updateBackgroundView() self.updateBackgroundView()

View File

@ -22,7 +22,7 @@ class PauseStoryboardSegue: UIStoryboardSegue
override func perform() override func perform()
{ {
self.destinationViewController.transitioningDelegate = self self.destinationViewController.transitioningDelegate = self
self.destinationViewController.modalPresentationStyle = .Custom self.destinationViewController.modalPresentationStyle = .custom
self.destinationViewController.modalPresentationCapturesStatusBarAppearance = true self.destinationViewController.modalPresentationCapturesStatusBarAppearance = true
super.perform() super.perform()
@ -31,17 +31,17 @@ class PauseStoryboardSegue: UIStoryboardSegue
extension PauseStoryboardSegue: UIViewControllerTransitioningDelegate extension PauseStoryboardSegue: UIViewControllerTransitioningDelegate
{ {
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?
{ {
return self return self
} }
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?
{ {
return nil return nil
} }
func presentationControllerForPresentedViewController(presentedViewController: UIViewController, presentingViewController: UIViewController, sourceViewController source: UIViewController) -> UIPresentationController? func presentationController(forPresented presentedViewController: UIViewController, presenting presentingViewController: UIViewController?, source: UIViewController) -> UIPresentationController?
{ {
return self.presentationController return self.presentationController
} }
@ -49,20 +49,20 @@ extension PauseStoryboardSegue: UIViewControllerTransitioningDelegate
extension PauseStoryboardSegue: UIViewControllerAnimatedTransitioning extension PauseStoryboardSegue: UIViewControllerAnimatedTransitioning
{ {
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval
{ {
return 0.65 return 0.65
} }
func animateTransition(transitionContext: UIViewControllerContextTransitioning) func animateTransition(using transitionContext: UIViewControllerContextTransitioning)
{ {
let destinationViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)! let destinationViewController = transitionContext.viewController(forKey: UITransitionContextToViewControllerKey)!
destinationViewController.view.frame = transitionContext.finalFrameForViewController(destinationViewController) destinationViewController.view.frame = transitionContext.finalFrame(for: destinationViewController)
destinationViewController.view.frame.origin.y = transitionContext.containerView()!.bounds.height destinationViewController.view.frame.origin.y = transitionContext.containerView().bounds.height
transitionContext.containerView()!.addSubview(destinationViewController.view) transitionContext.containerView().addSubview(destinationViewController.view)
UIView.animateWithDuration(self.transitionDuration(transitionContext), delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: [], animations: { UIView.animate(withDuration: self.transitionDuration(using: transitionContext), delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: [], animations: {
// Calling layoutIfNeeded before the animation block for some reason prevents the blur from fading in // Calling layoutIfNeeded before the animation block for some reason prevents the blur from fading in
// Additionally, if it's animated, it looks weird // Additionally, if it's animated, it looks weird

View File

@ -21,25 +21,25 @@ class PauseTransitionCoordinator: NSObject, UIViewControllerAnimatedTransitionin
super.init() super.init()
} }
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval
{ {
return 0.4 return 0.4
} }
func animateTransition(transitionContext: UIViewControllerContextTransitioning) func animateTransition(using transitionContext: UIViewControllerContextTransitioning)
{ {
let destinationViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)! let destinationViewController = transitionContext.viewController(forKey: UITransitionContextToViewControllerKey)!
let sourceViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)! let sourceViewController = transitionContext.viewController(forKey: UITransitionContextFromViewControllerKey)!
destinationViewController.view.frame = transitionContext.finalFrameForViewController(destinationViewController) destinationViewController.view.frame = transitionContext.finalFrame(for: destinationViewController)
destinationViewController.view.frame.origin.y = self.presenting ? transitionContext.containerView()!.bounds.height : -destinationViewController.view.bounds.height destinationViewController.view.frame.origin.y = self.presenting ? transitionContext.containerView().bounds.height : -destinationViewController.view.bounds.height
transitionContext.containerView()!.addSubview(destinationViewController.view) transitionContext.containerView().addSubview(destinationViewController.view)
destinationViewController.view.layoutIfNeeded() destinationViewController.view.layoutIfNeeded()
UIView.animateWithDuration(self.transitionDuration(transitionContext), delay:0, options:RSTSystemTransitionAnimationCurve, animations: { UIView.animate(withDuration: self.transitionDuration(using: transitionContext), delay:0, options:RSTSystemTransitionAnimationCurve, animations: {
sourceViewController.view.frame.origin.y = self.presenting ? -sourceViewController.view.bounds.height : transitionContext.containerView()!.bounds.height sourceViewController.view.frame.origin.y = self.presenting ? -sourceViewController.view.bounds.height : transitionContext.containerView().bounds.height
destinationViewController.view.frame.origin.y = 0 destinationViewController.view.frame.origin.y = 0
self.presentationController.containerView?.setNeedsLayout() self.presentationController.containerView?.setNeedsLayout()

View File

@ -11,15 +11,15 @@ import DeltaCore
private enum ControllersSettingsSection: Int private enum ControllersSettingsSection: Int
{ {
case None case none
case LocalDevice case localDevice
case ExternalControllers case externalControllers
} }
private class LocalDeviceController: ExternalController private class LocalDeviceController: ExternalController
{ {
override var name: String { override var name: String {
return UIDevice.currentDevice().name return UIDevice.current().name
} }
} }
@ -39,7 +39,7 @@ class ControllersSettingsViewController: UITableViewController
} }
} }
private var connectedControllers = ExternalControllerManager.sharedManager.connectedControllers.sort({ $0.playerIndex ?? NSIntegerMax < $1.playerIndex ?? NSIntegerMax }) private var connectedControllers = ExternalControllerManager.sharedManager.connectedControllers.sorted(isOrderedBefore: { $0.playerIndex ?? NSIntegerMax < $1.playerIndex ?? NSIntegerMax })
private lazy var localDeviceController: LocalDeviceController = { private lazy var localDeviceController: LocalDeviceController = {
let device = LocalDeviceController() let device = LocalDeviceController()
@ -52,8 +52,8 @@ class ControllersSettingsViewController: UITableViewController
{ {
super.init(coder: aDecoder) super.init(coder: aDecoder)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ControllersSettingsViewController.externalControllerDidConnect(_:)), name: ExternalControllerDidConnectNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(ControllersSettingsViewController.externalControllerDidConnect(_:)), name: ExternalControllerDidConnectNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ControllersSettingsViewController.externalControllerDidDisconnect(_:)), name: ExternalControllerDidDisconnectNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(ControllersSettingsViewController.externalControllerDidDisconnect(_:)), name: ExternalControllerDidDisconnectNotification, object: nil)
} }
override func viewDidLoad() override func viewDidLoad()
@ -63,7 +63,7 @@ class ControllersSettingsViewController: UITableViewController
//MARK: - Storyboards - //MARK: - Storyboards -
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
{ {
guard let indexPath = self.tableView.indexPathForSelectedRow else { return } guard let indexPath = self.tableView.indexPathForSelectedRow else { return }
@ -71,18 +71,18 @@ class ControllersSettingsViewController: UITableViewController
controllers.append(self.localDeviceController) controllers.append(self.localDeviceController)
// Reset previous controller // Reset previous controller
if let playerIndex = self.playerIndex, index = controllers.indexOf({ $0.playerIndex == playerIndex }) if let playerIndex = self.playerIndex, index = controllers.index(where: { $0.playerIndex == playerIndex })
{ {
let controller = controllers[index] let controller = controllers[index]
controller.playerIndex = nil controller.playerIndex = nil
} }
switch ControllersSettingsSection(rawValue: indexPath.section)! switch ControllersSettingsSection(rawValue: (indexPath as NSIndexPath).section)!
{ {
case .None: break case .none: break
case .LocalDevice: self.localDeviceController.playerIndex = self.playerIndex case .localDevice: self.localDeviceController.playerIndex = self.playerIndex
case .ExternalControllers: case .externalControllers:
let controller = self.connectedControllers[indexPath.row] let controller = self.connectedControllers[(indexPath as NSIndexPath).row]
controller.playerIndex = self.playerIndex controller.playerIndex = self.playerIndex
} }
@ -93,60 +93,60 @@ class ControllersSettingsViewController: UITableViewController
private extension ControllersSettingsViewController private extension ControllersSettingsViewController
{ {
dynamic func externalControllerDidConnect(notification: NSNotification) dynamic func externalControllerDidConnect(_ notification: Notification)
{ {
guard let controller = notification.object as? ExternalController else { return } guard let controller = notification.object as? ExternalController else { return }
if let playerIndex = controller.playerIndex if let playerIndex = controller.playerIndex
{ {
self.connectedControllers.insert(controller, atIndex: playerIndex) self.connectedControllers.insert(controller, at: playerIndex)
} }
else else
{ {
self.connectedControllers.append(controller) self.connectedControllers.append(controller)
} }
if let index = self.connectedControllers.indexOf(controller) if let index = self.connectedControllers.index(of: controller)
{ {
if self.connectedControllers.count == 1 if self.connectedControllers.count == 1
{ {
self.tableView.insertSections(NSIndexSet(index: ControllersSettingsSection.ExternalControllers.rawValue), withRowAnimation: .Fade) self.tableView.insertSections(IndexSet(integer: ControllersSettingsSection.externalControllers.rawValue), with: .fade)
} }
else else
{ {
self.tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: index, inSection: ControllersSettingsSection.ExternalControllers.rawValue)], withRowAnimation: .Automatic) self.tableView.insertRows(at: [IndexPath(row: index, section: ControllersSettingsSection.externalControllers.rawValue)], with: .automatic)
} }
} }
} }
dynamic func externalControllerDidDisconnect(notification: NSNotification) dynamic func externalControllerDidDisconnect(_ notification: Notification)
{ {
guard let controller = notification.object as? ExternalController else { return } guard let controller = notification.object as? ExternalController else { return }
if let index = self.connectedControllers.indexOf(controller) if let index = self.connectedControllers.index(of: controller)
{ {
self.connectedControllers.removeAtIndex(index) self.connectedControllers.remove(at: index)
if self.connectedControllers.count == 0 if self.connectedControllers.count == 0
{ {
self.tableView.deleteSections(NSIndexSet(index: ControllersSettingsSection.ExternalControllers.rawValue), withRowAnimation: .Fade) self.tableView.deleteSections(IndexSet(integer: ControllersSettingsSection.externalControllers.rawValue), with: .fade)
} }
else else
{ {
self.tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: index, inSection: ControllersSettingsSection.ExternalControllers.rawValue)], withRowAnimation: .Automatic) self.tableView.deleteRows(at: [IndexPath(row: index, section: ControllersSettingsSection.externalControllers.rawValue)], with: .automatic)
} }
} }
if controller.playerIndex == self.playerIndex if controller.playerIndex == self.playerIndex
{ {
self.tableView.reloadSections(NSIndexSet(index: ControllersSettingsSection.None.rawValue), withRowAnimation: .None) self.tableView.reloadSections(IndexSet(integer: ControllersSettingsSection.none.rawValue), with: .none)
} }
} }
} }
extension ControllersSettingsViewController extension ControllersSettingsViewController
{ {
override func numberOfSectionsInTableView(tableView: UITableView) -> Int override func numberOfSections(in tableView: UITableView) -> Int
{ {
if self.connectedControllers.count == 0 if self.connectedControllers.count == 0
{ {
@ -156,42 +156,42 @@ extension ControllersSettingsViewController
return 3 return 3
} }
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{ {
switch ControllersSettingsSection(rawValue: section)! switch ControllersSettingsSection(rawValue: section)!
{ {
case .None: return 1 case .none: return 1
case .LocalDevice: return 1 case .localDevice: return 1
case .ExternalControllers: return self.connectedControllers.count case .externalControllers: return self.connectedControllers.count
} }
} }
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{ {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.detailTextLabel?.text = nil cell.detailTextLabel?.text = nil
cell.accessoryType = .None cell.accessoryType = .none
if indexPath.section == ControllersSettingsSection.None.rawValue if (indexPath as NSIndexPath).section == ControllersSettingsSection.none.rawValue
{ {
cell.textLabel?.text = NSLocalizedString("None", comment: "") cell.textLabel?.text = NSLocalizedString("None", comment: "")
if Settings.localControllerPlayerIndex != self.playerIndex && !self.connectedControllers.contains({ $0.playerIndex == self.playerIndex }) if Settings.localControllerPlayerIndex != self.playerIndex && !self.connectedControllers.contains({ $0.playerIndex == self.playerIndex })
{ {
cell.accessoryType = .Checkmark cell.accessoryType = .checkmark
} }
} }
else else
{ {
let controller: ExternalController let controller: ExternalController
if indexPath.section == ControllersSettingsSection.LocalDevice.rawValue if (indexPath as NSIndexPath).section == ControllersSettingsSection.localDevice.rawValue
{ {
controller = self.localDeviceController controller = self.localDeviceController
} }
else if indexPath.section == ControllersSettingsSection.ExternalControllers.rawValue else if (indexPath as NSIndexPath).section == ControllersSettingsSection.externalControllers.rawValue
{ {
controller = self.connectedControllers[indexPath.row] controller = self.connectedControllers[(indexPath as NSIndexPath).row]
} }
else else
{ {
@ -202,7 +202,7 @@ extension ControllersSettingsViewController
if controller.playerIndex == self.playerIndex if controller.playerIndex == self.playerIndex
{ {
cell.accessoryType = .Checkmark cell.accessoryType = .checkmark
} }
else else
{ {
@ -217,13 +217,13 @@ extension ControllersSettingsViewController
return cell return cell
} }
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
{ {
switch ControllersSettingsSection(rawValue: section)! switch ControllersSettingsSection(rawValue: section)!
{ {
case .None: return nil case .none: return nil
case .LocalDevice: return NSLocalizedString("Local Device", comment: "") case .localDevice: return NSLocalizedString("Local Device", comment: "")
case .ExternalControllers: return self.connectedControllers.count > 0 ? NSLocalizedString("External Controllers", comment: "") : "" case .externalControllers: return self.connectedControllers.count > 0 ? NSLocalizedString("External Controllers", comment: "") : ""
} }
} }
} }

View File

@ -11,7 +11,7 @@ import DeltaCore
private enum SettingsSection: Int private enum SettingsSection: Int
{ {
case Controllers case controllers
} }
private enum SettingsSegues: String private enum SettingsSegues: String
@ -25,8 +25,8 @@ class SettingsViewController: UITableViewController
{ {
super.init(coder: aDecoder) super.init(coder: aDecoder)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SettingsViewController.externalControllerDidConnect(_:)), name: ExternalControllerDidConnectNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(SettingsViewController.externalControllerDidConnect(_:)), name: ExternalControllerDidConnectNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SettingsViewController.externalControllerDidDisconnect(_:)), name: ExternalControllerDidDisconnectNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(SettingsViewController.externalControllerDidDisconnect(_:)), name: ExternalControllerDidDisconnectNotification, object: nil)
} }
override func viewDidLoad() override func viewDidLoad()
@ -34,13 +34,13 @@ class SettingsViewController: UITableViewController
super.viewDidLoad() super.viewDidLoad()
} }
override func viewWillAppear(animated: Bool) override func viewWillAppear(_ animated: Bool)
{ {
super.viewWillAppear(animated) super.viewWillAppear(animated)
if let indexPath = self.tableView.indexPathForSelectedRow if let indexPath = self.tableView.indexPathForSelectedRow
{ {
self.tableView.deselectRowAtIndexPath(indexPath, animated: true) self.tableView.deselectRow(at: indexPath, animated: true)
} }
} }
@ -49,54 +49,54 @@ class SettingsViewController: UITableViewController
super.didReceiveMemoryWarning() super.didReceiveMemoryWarning()
} }
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
{ {
if segue.identifier == SettingsSegues.Controllers.rawValue if segue.identifier == SettingsSegues.Controllers.rawValue
{ {
let controllersSettingsViewController = segue.destinationViewController as! ControllersSettingsViewController let controllersSettingsViewController = segue.destinationViewController as! ControllersSettingsViewController
controllersSettingsViewController.playerIndex = self.tableView.indexPathForSelectedRow?.row controllersSettingsViewController.playerIndex = (self.tableView.indexPathForSelectedRow as NSIndexPath?)?.row
} }
} }
} }
private extension SettingsViewController private extension SettingsViewController
{ {
@IBAction func unwindFromControllersSettingsViewController(segue: UIStoryboardSegue) @IBAction func unwindFromControllersSettingsViewController(_ segue: UIStoryboardSegue)
{ {
let indexPath = self.tableView.indexPathForSelectedRow let indexPath = self.tableView.indexPathForSelectedRow
self.tableView.reloadSections(NSIndexSet(index: SettingsSection.Controllers.rawValue), withRowAnimation: .None) self.tableView.reloadSections(IndexSet(integer: SettingsSection.controllers.rawValue), with: .none)
self.tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: UITableViewScrollPosition.None) self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: UITableViewScrollPosition.none)
} }
} }
private extension SettingsViewController private extension SettingsViewController
{ {
dynamic func externalControllerDidConnect(notification: NSNotification) dynamic func externalControllerDidConnect(_ notification: Notification)
{ {
self.tableView.reloadSections(NSIndexSet(index: SettingsSection.Controllers.rawValue), withRowAnimation: .None) self.tableView.reloadSections(IndexSet(integer: SettingsSection.controllers.rawValue), with: .none)
} }
dynamic func externalControllerDidDisconnect(notification: NSNotification) dynamic func externalControllerDidDisconnect(_ notification: Notification)
{ {
self.tableView.reloadSections(NSIndexSet(index: SettingsSection.Controllers.rawValue), withRowAnimation: .None) self.tableView.reloadSections(IndexSet(integer: SettingsSection.controllers.rawValue), with: .none)
} }
} }
extension SettingsViewController extension SettingsViewController
{ {
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{ {
let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath) let cell = super.tableView(tableView, cellForRowAt: indexPath)
if indexPath.section == SettingsSection.Controllers.rawValue if (indexPath as NSIndexPath).section == SettingsSection.controllers.rawValue
{ {
if indexPath.row == Settings.localControllerPlayerIndex if (indexPath as NSIndexPath).row == Settings.localControllerPlayerIndex
{ {
cell.detailTextLabel?.text = UIDevice.currentDevice().name cell.detailTextLabel?.text = UIDevice.current().name
} }
else if let index = ExternalControllerManager.sharedManager.connectedControllers.indexOf({ $0.playerIndex == indexPath.row }) else if let index = ExternalControllerManager.sharedManager.connectedControllers.index(where: { $0.playerIndex == (indexPath as NSIndexPath).row })
{ {
let controller = ExternalControllerManager.sharedManager.connectedControllers[index] let controller = ExternalControllerManager.sharedManager.connectedControllers[index]
cell.detailTextLabel?.text = controller.name cell.detailTextLabel?.text = controller.name
@ -110,11 +110,11 @@ extension SettingsViewController
return cell return cell
} }
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{ {
if indexPath.section == SettingsSection.Controllers.rawValue if (indexPath as NSIndexPath).section == SettingsSection.controllers.rawValue
{ {
self.performSegueWithIdentifier(SettingsSegues.Controllers.rawValue, sender: self) self.performSegue(withIdentifier: SettingsSegues.Controllers.rawValue, sender: self)
} }
} }
} }

View File

@ -232,6 +232,14 @@
attributes = { attributes = {
LastSwiftUpdateCheck = 0700; LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700; LastUpgradeCheck = 0700;
TargetAttributes = {
0A60B5C71D5A2CFF92811AA9AEC27278 = {
LastSwiftMigration = 0800;
};
B20CFA992EEA3E3A903F2359B05A88E1 = {
LastSwiftMigration = 0800;
};
};
}; };
buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */;
compatibilityVersion = "Xcode 3.2"; compatibilityVersion = "Xcode 3.2";
@ -303,6 +311,7 @@
PRODUCT_NAME = Pods; PRODUCT_NAME = Pods;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TVOS_DEPLOYMENT_TARGET = 9.0; TVOS_DEPLOYMENT_TARGET = 9.0;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = ""; VERSION_INFO_PREFIX = "";
@ -328,6 +337,7 @@
PRODUCT_NAME = FileMD5Hash; PRODUCT_NAME = FileMD5Hash;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TVOS_DEPLOYMENT_TARGET = 9.0; TVOS_DEPLOYMENT_TARGET = 9.0;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = ""; VERSION_INFO_PREFIX = "";
@ -353,6 +363,7 @@
PRODUCT_NAME = FileMD5Hash; PRODUCT_NAME = FileMD5Hash;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TVOS_DEPLOYMENT_TARGET = 9.0; TVOS_DEPLOYMENT_TARGET = 9.0;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = ""; VERSION_INFO_PREFIX = "";
@ -420,6 +431,7 @@
PRODUCT_NAME = Pods; PRODUCT_NAME = Pods;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TVOS_DEPLOYMENT_TARGET = 9.0; TVOS_DEPLOYMENT_TARGET = 9.0;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = ""; VERSION_INFO_PREFIX = "";