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()
var predicates: [NSPredicate] = []
var predicates: [Predicate] = []
if let identifiers = self.supportedGameCollectionIdentifiers
{
for identifier in identifiers
{
let predicate = NSPredicate(format: "SUBQUERY(%K, $x, $x.%K == %@).@count > 0", Game.Attributes.gameCollections.rawValue, GameCollection.Attributes.identifier.rawValue, identifier)
let predicate = Predicate(format: "SUBQUERY(%K, $x, $x.%K == %@).@count > 0", Game.Attributes.gameCollections.rawValue, GameCollection.Attributes.identifier.rawValue, identifier)
predicates.append(predicate)
}
}
if predicates.count > 0
{
fetchRequest.predicate = NSCompoundPredicate(orPredicateWithSubpredicates: predicates)
fetchRequest.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.delegate = previousDelegate
@ -72,9 +72,9 @@ class GameCollectionViewDataSource: NSObject
// 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
{
@ -85,20 +85,20 @@ class GameCollectionViewDataSource: NSObject
extension GameCollectionViewDataSource: UICollectionViewDataSource
{
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
func numberOfSections(in collectionView: UICollectionView) -> Int
{
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
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)
@ -108,18 +108,18 @@ extension GameCollectionViewDataSource: UICollectionViewDataSource
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 widthConstraint = self.prototypeCell.contentView.widthAnchor.constraintEqualToConstant(collectionViewLayout.itemWidth)
widthConstraint.active = true
let widthConstraint = self.prototypeCell.contentView.widthAnchor.constraint(equalToConstant: collectionViewLayout.itemWidth)
widthConstraint.isActive = true
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
}

View File

@ -44,44 +44,44 @@ class GridCollectionViewCell: UICollectionViewCell
private func configureSubviews()
{
// 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.contentView.clipsToBounds = false
self.imageView.translatesAutoresizingMaskIntoConstraints = false
self.imageView.contentMode = .ScaleAspectFit
self.imageView.contentMode = .scaleAspectFit
#if os(tvOS)
self.imageView.adjustsImageWhenAncestorFocused = true
#endif
self.contentView.addSubview(self.imageView)
self.textLabel.translatesAutoresizingMaskIntoConstraints = false
self.textLabel.font = UIFont.boldSystemFontOfSize(12)
self.textLabel.textAlignment = .Center
self.textLabel.font = UIFont.boldSystemFont(ofSize: 12)
self.textLabel.textAlignment = .center
self.textLabel.numberOfLines = 0
self.contentView.addSubview(self.textLabel)
// Auto Layout
self.imageView.topAnchor.constraintEqualToAnchor(self.contentView.topAnchor).active = true
self.imageView.centerXAnchor.constraintEqualToAnchor(self.contentView.centerXAnchor).active = true
self.imageView.topAnchor.constraint(equalTo: self.contentView.topAnchor).isActive = true
self.imageView.centerXAnchor.constraint(equalTo: self.contentView.centerXAnchor).isActive = true
self.imageViewWidthConstraint = self.imageView.widthAnchor.constraintEqualToConstant(self.maximumImageSize.width)
self.imageViewWidthConstraint.active = true
self.imageViewWidthConstraint = self.imageView.widthAnchor.constraint(equalToConstant: self.maximumImageSize.width)
self.imageViewWidthConstraint.isActive = true
self.imageViewHeightConstraint = self.imageView.heightAnchor.constraintEqualToConstant(self.maximumImageSize.height)
self.imageViewHeightConstraint.active = true
self.imageViewHeightConstraint = self.imageView.heightAnchor.constraint(equalToConstant: self.maximumImageSize.height)
self.imageViewHeightConstraint.isActive = true
self.textLabel.trailingAnchor.constraintEqualToAnchor(self.contentView.trailingAnchor).active = true
self.textLabel.leadingAnchor.constraintEqualToAnchor(self.contentView.leadingAnchor).active = true
self.textLabel.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor).isActive = true
self.textLabel.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor).isActive = true
self.textLabelBottomAnchorConstraint = self.textLabel.bottomAnchor.constraintEqualToAnchor(self.contentView.bottomAnchor)
self.textLabelBottomAnchorConstraint.active = true
self.textLabelBottomAnchorConstraint = self.textLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor)
self.textLabelBottomAnchorConstraint.isActive = true
self.textLabelVerticalSpacingConstraint = self.textLabel.topAnchor.constraintEqualToAnchor(self.imageView.bottomAnchor)
self.textLabelVerticalSpacingConstraint.active = true
self.textLabelVerticalSpacingConstraint = self.textLabel.topAnchor.constraint(equalTo: self.imageView.bottomAnchor)
self.textLabelVerticalSpacingConstraint.isActive = true
#if os(tvOS)
@ -90,37 +90,37 @@ class GridCollectionViewCell: UICollectionViewCell
self.textLabelFocusedVerticalSpacingConstraint = self.textLabel.topAnchor.constraintEqualToAnchor(self.imageView.focusedFrameGuide.bottomAnchor, constant: 0)
self.textLabelFocusedVerticalSpacingConstraint?.active = true
#else
self.textLabelVerticalSpacingConstraint.active = true
self.textLabelVerticalSpacingConstraint.isActive = true
#endif
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({
if context.nextFocusedView == self
{
self.textLabelBottomAnchorConstraint?.active = false
self.textLabelVerticalSpacingConstraint.active = false
self.textLabelBottomAnchorConstraint?.isActive = false
self.textLabelVerticalSpacingConstraint.isActive = false
self.textLabelFocusedVerticalSpacingConstraint?.active = true
self.textLabelFocusedVerticalSpacingConstraint?.isActive = true
self.textLabel.textColor = UIColor.whiteColor()
self.textLabel.textColor = UIColor.white()
}
else
{
self.textLabelFocusedVerticalSpacingConstraint?.active = false
self.textLabelFocusedVerticalSpacingConstraint?.isActive = false
self.textLabelBottomAnchorConstraint?.active = true
self.textLabelVerticalSpacingConstraint.active = true
self.textLabelBottomAnchorConstraint?.isActive = true
self.textLabelVerticalSpacingConstraint.isActive = true
self.textLabel.textColor = UIColor.blackColor()
self.textLabel.textColor = UIColor.black()
}
self.layoutIfNeeded()
@ -139,4 +139,4 @@ private extension GridCollectionViewCell
self.textLabelVerticalSpacingConstraint.constant = 8
self.textLabelFocusedVerticalSpacingConstraint?.constant = self.maximumImageSize.height / 10.0
}
}
}

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 }
@ -39,7 +39,7 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
self.sectionInset.left = 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 maximumY: CGFloat? = nil
@ -47,9 +47,9 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
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)
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)
for (index, layoutAttributes) in tempLayoutAttributes.enumerate()
for (index, layoutAttributes) in tempLayoutAttributes.enumerated()
{
layoutAttributes.frame.origin.x = spacing + (spacing + self.itemWidth) * CGFloat(index)
}
@ -117,7 +117,7 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
private extension GridCollectionViewLayout
{
func alignLayoutAttributes(layoutAttributes: [UICollectionViewLayoutAttributes], toMinimumY minimumY: CGFloat)
func alignLayoutAttributes(_ layoutAttributes: [UICollectionViewLayoutAttributes], toMinimumY minimumY: CGFloat)
{
for attributes in layoutAttributes
{

View File

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

View File

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

View File

@ -13,9 +13,9 @@ import Roxas
public class LoadImageOperation: RSTOperation
{
public let URL: NSURL
public let URL: Foundation.URL
public var completionHandler: (UIImage? -> Void)? {
public var completionHandler: ((UIImage?) -> Void)? {
didSet {
self.completionBlock = {
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 {
// 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?
public init(URL: NSURL)
public init(URL: Foundation.URL)
{
self.URL = URL
@ -46,9 +46,9 @@ public extension LoadImageOperation
{
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
return
@ -58,11 +58,11 @@ public extension LoadImageOperation
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
UIGraphicsBeginImageContextWithOptions(CGSize(width: 1, height: 1), true, 1.0)
loadedImage.drawAtPoint(CGPoint.zero)
loadedImage.draw(at: CGPoint.zero)
UIGraphicsEndImageContext()
self.imageCache?.setObject(loadedImage, forKey: self.URL)
@ -70,4 +70,4 @@ public extension LoadImageOperation
self.image = loadedImage
}
}
}
}

View File

@ -29,46 +29,46 @@ class DatabaseManager
private init()
{
let modelURL = NSBundle.mainBundle().URLForResource("Model", withExtension: "momd")
let managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL!)
let modelURL = Bundle.main.urlForResource("Model", withExtension: "momd")
let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL!)
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel!)
self.privateManagedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
self.privateManagedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
self.privateManagedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator
self.privateManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
self.managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
self.managedObjectContext.parentContext = self.privateManagedObjectContext
self.managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
self.managedObjectContext.parent = self.privateManagedObjectContext
self.managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
self.validationManagedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
self.validationManagedObjectContext.parentContext = self.managedObjectContext
self.validationManagedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
self.validationManagedObjectContext.parent = self.managedObjectContext
self.validationManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(DatabaseManager.managedObjectContextWillSave(_:)), name: NSManagedObjectContextWillSaveNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(DatabaseManager.managedObjectContextDidSave(_:)), name: NSManagedObjectContextDidSaveNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(DatabaseManager.managedObjectContextWillSave(_:)), name: NSNotification.Name.NSManagedObjectContextWillSave, 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]
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
{
performingMigration = !managedObjectModel.isConfiguration(nil, compatibleWithStoreMetadata: sourceMetadata)
performingMigration = !managedObjectModel.isConfiguration(withName: nil, compatibleWithStoreMetadata: sourceMetadata)
}
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
{
@ -94,16 +94,16 @@ class DatabaseManager
// MARK: - Importing -
/// Importing
func importGamesAtURLs(URLs: [NSURL], withCompletion completion: ([String] -> Void)?)
func importGamesAtURLs(_ URLs: [URL], withCompletion completion: (([String]) -> Void)?)
{
let managedObjectContext = self.backgroundManagedObjectContext()
managedObjectContext.performBlock() {
managedObjectContext.perform() {
var identifiers: [String] = []
for URL in URLs
{
let identifier = FileHash.sha1HashOfFileAtPath(URL.path) as String
let identifier = FileHash.sha1HashOfFile(atPath: URL.path) as String
var filename = identifier
if let pathExtension = URL.pathExtension
@ -112,7 +112,7 @@ class DatabaseManager
}
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.filename = filename
@ -129,17 +129,17 @@ class DatabaseManager
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 NSFileManager.defaultManager().fileExistsAtPath(path)
if FileManager.default.fileExists(atPath: path)
{
try NSFileManager.defaultManager().removeItemAtURL(URL)
try FileManager.default.removeItem(at: URL)
}
else
{
try NSFileManager.defaultManager().moveItemAtURL(URL, toURL: destinationURL)
try FileManager.default.moveItem(at: URL, to: destinationURL)
}
}
@ -147,7 +147,7 @@ class DatabaseManager
}
catch
{
game.managedObjectContext?.deleteObject(game)
game.managedObjectContext?.delete(game)
}
}
@ -177,8 +177,8 @@ class DatabaseManager
func backgroundManagedObjectContext() -> NSManagedObjectContext
{
let managedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
managedObjectContext.parentContext = self.validationManagedObjectContext
let managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
managedObjectContext.parent = self.validationManagedObjectContext
managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
return managedObjectContext
@ -187,44 +187,44 @@ class 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
{
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)
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)
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)
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)
return gameDirectoryURL
@ -239,7 +239,7 @@ private extension DatabaseManager
{
let backgroundTaskIdentifier = RSTBeginBackgroundTask("Save Database Task")
self.validationManagedObjectContext.performBlockAndWait {
self.validationManagedObjectContext.performAndWait {
do
{
@ -252,7 +252,7 @@ private extension DatabaseManager
// Update main managed object context
self.managedObjectContext.performBlockAndWait() {
self.managedObjectContext.performAndWait() {
do
{
@ -265,7 +265,7 @@ private extension DatabaseManager
// Save to disk
self.privateManagedObjectContext.performBlock() {
self.privateManagedObjectContext.perform() {
do
{
@ -287,22 +287,22 @@ private extension DatabaseManager
// MARK: - Validation -
func validateManagedObjectContextSave(managedObjectContext: NSManagedObjectContext)
func validateManagedObjectContextSave(_ managedObjectContext: NSManagedObjectContext)
{
// Remove deleted files from disk
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
{
case let game as Game:
fileURLs.insert(game.fileURL)
fileURLs.insert(game.fileURL as URL)
case let saveState as SaveState:
fileURLs.insert(saveState.fileURL)
fileURLs.insert(saveState.imageFileURL)
fileURLs.insert(saveState.fileURL as URL)
fileURLs.insert(saveState.imageFileURL as URL)
default: break
}
@ -311,7 +311,7 @@ private extension DatabaseManager
{
do
{
try NSFileManager.defaultManager().removeItemAtURL(URL)
try FileManager.default.removeItem(at: URL)
}
catch let error as NSError
{
@ -321,43 +321,43 @@ private extension DatabaseManager
}
// 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
{
self.validationManagedObjectContext.deleteObject(collection)
self.validationManagedObjectContext.delete(collection)
}
}
// 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)
}
}
@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()
}
// MARK: - File Management -
class func createDirectoryAtURLIfNeeded(URL: NSURL)
class func createDirectoryAtURLIfNeeded(_ URL: Foundation.URL)
{
do
{
try NSFileManager.defaultManager().createDirectoryAtURL(URL, withIntermediateDirectories: true, attributes: nil)
try FileManager.default.createDirectory(at: URL, withIntermediateDirectories: true, attributes: nil)
}
catch
{
print(error)
}
}
}
}

View File

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

View File

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

View File

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

View File

@ -15,31 +15,31 @@ extension NSManagedObject
return NSStringFromClass(self)
}
class func insertIntoManagedObjectContext(managedObjectContext: NSManagedObjectContext) -> Self
class func insertIntoManagedObjectContext(_ managedObjectContext: NSManagedObjectContext) -> 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
}
// MARK: - Fetches -
class func fetchRequest() -> NSFetchRequest
class func fetchRequest() -> NSFetchRequest<AnyObject>
{
let fetchRequest = NSFetchRequest(entityName: self.entityName)
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)
}
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()
fetchRequest.predicate = predicate
@ -48,7 +48,7 @@ extension NSManagedObject
do
{
results = try managedObjectContext.executeFetchRequest(fetchRequest) as! [T]
results = try managedObjectContext.fetch(fetchRequest) as! [T]
}
catch let error as NSError
{

View File

@ -13,15 +13,15 @@ import DeltaCore
protocol GamePickerControllerDelegate
{
func gamePickerController(gamePickerController: GamePickerController, didImportGames games: [Game])
func gamePickerController(_ gamePickerController: GamePickerController, didImportGames games: [Game])
/** Optional **/
func gamePickerControllerDidCancel(gamePickerController: GamePickerController)
func gamePickerControllerDidCancel(_ gamePickerController: GamePickerController)
}
extension GamePickerControllerDelegate
{
func gamePickerControllerDidCancel(gamePickerController: GamePickerController)
func gamePickerControllerDidCancel(_ gamePickerController: GamePickerController)
{
// Empty Implementation
}
@ -33,34 +33,34 @@ class GamePickerController: NSObject
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
#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.addOptionWithTitle(NSLocalizedString("iTunes", comment: ""), image: nil, order: .First) { self.importFromiTunes(nil) }
self.presentingViewController?.presentViewController(documentMenuController, animated: true, completion: nil)
documentMenuController.addOption(withTitle: NSLocalizedString("iTunes", comment: ""), image: nil, order: .first) { self.importFromiTunes(nil) }
self.presentingViewController?.present(documentMenuController, animated: true, completion: nil)
#else
self.importFromiTunes(completion)
#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
{
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()
managedObjectContext.performBlock() {
managedObjectContext.perform() {
let gameURLs = contents.filter({ GameCollection.gameSystemCollectionForPathExtension($0.pathExtension, inManagedObjectContext: managedObjectContext).identifier != kUTTypeDeltaGame as String })
self.importGamesAtURLs(gameURLs)
}
@ -76,22 +76,22 @@ class GamePickerController: NSObject
}
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.presentingViewController?.gamePickerController = nil
}
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.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)
self.delegate?.gamePickerController(self, didImportGames: games)
@ -107,15 +107,15 @@ class GamePickerController: NSObject
extension GamePickerController: UIDocumentMenuDelegate
{
func documentMenu(documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController)
func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController)
{
documentPicker.delegate = self
self.presentingViewController?.presentViewController(documentPicker, animated: true, completion: nil)
self.presentingViewController?.present(documentPicker, animated: true, completion: nil)
self.presentingViewController?.gamePickerController = nil
}
func documentMenuWasCancelled(documentMenu: UIDocumentMenuViewController)
func documentMenuWasCancelled(_ documentMenu: UIDocumentMenuViewController)
{
self.delegate?.gamePickerControllerDidCancel(self)
@ -126,14 +126,14 @@ class GamePickerController: NSObject
extension GamePickerController: UIDocumentPickerDelegate
{
func documentPicker(controller: UIDocumentPickerViewController, didPickDocumentAtURL url: NSURL)
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL)
{
self.importGamesAtURLs([url])
self.presentingViewController?.gamePickerController = nil
}
func documentPickerWasCancelled(controller: UIDocumentPickerViewController)
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController)
{
self.delegate?.gamePickerControllerDidCancel(self)
@ -159,10 +159,10 @@ extension UIViewController
}
}
func presentGamePickerController(gamePickerController: GamePickerController, animated: Bool, completion: (Void -> Void)?)
func presentGamePickerController(_ gamePickerController: GamePickerController, animated: Bool, completion: ((Void) -> Void)?)
{
self.gamePickerController = gamePickerController
gamePickerController.presentGamePickerControllerFromPresentingViewController(self, animated: animated, completion: completion)
}
}
}

View File

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

View File

@ -15,19 +15,19 @@ class AppDelegate: UIResponder, UIApplicationDelegate
{
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()
// Database
let semaphore = dispatch_semaphore_create(0)
let semaphore = DispatchSemaphore(value: 0)
DatabaseManager.sharedManager.startWithCompletion { performingMigration in
dispatch_semaphore_signal(semaphore)
semaphore.signal()
}
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
semaphore.wait(timeout: DispatchTime.distantFuture)
// Controllers
ExternalControllerManager.sharedManager.startMonitoringExternalControllers()
@ -35,29 +35,29 @@ class AppDelegate: UIResponder, UIApplicationDelegate
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.
// 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.
// 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.
}
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.
}
func applicationWillTerminate(application: UIApplication)
func applicationWillTerminate(_ application: UIApplication)
{
// 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
private struct DispatchSemaphore: Hashable
{
let semaphore: dispatch_semaphore_t
let semaphore: Dispatch.DispatchSemaphore
var hashValue: Int {
return semaphore.hash
@ -22,7 +22,7 @@ private struct DispatchSemaphore: Hashable
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
// To workaround, we have this closure to defer work for Peeking/Popping until the view controller appears
// Hacky, but works
var deferredPreparationHandler: (Void -> Void)?
var deferredPreparationHandler: ((Void) -> Void)?
//MARK: - Private Properties
private var pauseViewController: PauseViewController?
@ -77,7 +77,7 @@ class EmulationViewController: UIViewController
private var updateSemaphores = Set<DispatchSemaphore>()
private var sustainedInputs = [ObjectIdentifier: [InputType]]()
private var reactivateSustainInputsQueue: NSOperationQueue
private var reactivateSustainInputsQueue: OperationQueue
private var choosingSustainedButtons = false
@IBOutlet private var controllerView: ControllerView!
@ -92,16 +92,16 @@ class EmulationViewController: UIViewController
/** Initializers **/
required init?(coder aDecoder: NSCoder)
{
self.reactivateSustainInputsQueue = NSOperationQueue()
self.reactivateSustainInputsQueue = OperationQueue()
self.reactivateSustainInputsQueue.maxConcurrentOperationCount = 1
super.init(coder: aDecoder)
NSNotificationCenter.defaultCenter().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: ExternalControllerDidConnectNotification, 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())
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(EmulationViewController.didBecomeActive(_:)), name: UIApplicationDidBecomeActiveNotification, object: UIApplication.sharedApplication())
NotificationCenter.default.addObserver(self, selector: #selector(EmulationViewController.willResignActive(_:)), name: NSNotification.Name.UIApplicationWillResignActive, object: UIApplication.shared())
NotificationCenter.default.addObserver(self, selector: #selector(EmulationViewController.didBecomeActive(_:)), name: NSNotification.Name.UIApplicationDidBecomeActive, object: UIApplication.shared())
}
deinit
@ -123,7 +123,7 @@ class EmulationViewController: UIViewController
// (such as when peeking and popping)
self.controllerViewHeightConstraint.constant = 0
self.gameView.backgroundColor = UIColor.clearColor()
self.gameView.backgroundColor = UIColor.clear()
self.emulatorCore.addGameView(self.gameView)
self.backgroundView.textLabel.text = NSLocalizedString("Select Buttons to Sustain", comment: "")
@ -137,7 +137,7 @@ class EmulationViewController: UIViewController
self.updateControllers()
}
override func viewDidAppear(animated: Bool)
override func viewDidAppear(_ animated: Bool)
{
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)
switch self.emulatorCore.state
{
case .Stopped:
case .stopped:
self.emulatorCore.startEmulation()
self.updateCheats()
case .Running: break
case .Paused:
case .running: break
case .paused:
self.updateCheats()
self.resumeEmulation()
}
@ -177,7 +177,7 @@ class EmulationViewController: UIViewController
self.controllerViewHeightConstraint.constant = 0
}
self.controllerView.hidden = self.isPreviewing
self.controllerView.isHidden = self.isPreviewing
}
override func prefersStatusBarHidden() -> Bool
@ -186,15 +186,15 @@ class EmulationViewController: UIViewController
}
/// <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()
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
self.gameView.inputImage = self.gameView.outputImage
@ -208,7 +208,7 @@ class EmulationViewController: UIViewController
// MARK: - 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()
@ -226,11 +226,11 @@ class EmulationViewController: UIViewController
// 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
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
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
@ -260,7 +260,7 @@ class EmulationViewController: UIViewController
}
}
@IBAction func unwindFromPauseViewController(segue: UIStoryboardSegue)
@IBAction func unwindFromPauseViewController(_ segue: UIStoryboardSegue)
{
self.pauseViewController = nil
self.pausingGameController = nil
@ -271,7 +271,7 @@ class EmulationViewController: UIViewController
self.emulatorCore.audioManager.enabled = false
// 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
}
}
@ -288,10 +288,10 @@ class EmulationViewController: UIViewController
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
dispatch_async(dispatch_get_main_queue()) {
presentingViewController?.presentViewController(viewController, animated: true, completion: nil)
DispatchQueue.main.async {
presentingViewController?.present(viewController, animated: true, completion: nil)
}
}
return [launchGameAction]
@ -302,9 +302,9 @@ class EmulationViewController: UIViewController
/// Emulation
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
@ -319,11 +319,11 @@ private extension EmulationViewController
return self.emulatorCore.resumeEmulation()
}
func emulatorCoreDidUpdate(emulatorCore: EmulatorCore)
func emulatorCoreDidUpdate(_ emulatorCore: EmulatorCore)
{
for semaphore in self.updateSemaphores
{
dispatch_semaphore_signal(semaphore.semaphore)
semaphore.semaphore.signal()
}
}
}
@ -345,7 +345,7 @@ private extension EmulationViewController
controllers.append(self.controllerView)
// 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
{
@ -370,17 +370,17 @@ private extension EmulationViewController
func showSustainButtonView()
{
self.choosingSustainedButtons = true
self.sustainButtonContentView.hidden = false
self.sustainButtonContentView.isHidden = false
}
func hideSustainButtonView()
{
self.choosingSustainedButtons = false
UIView.animateWithDuration(0.4, animations: {
UIView.animate(withDuration: 0.4, animations: {
self.sustainButtonContentView.alpha = 0.0
}) { (finished) in
self.sustainButtonContentView.hidden = true
self.sustainButtonContentView.isHidden = true
self.sustainButtonContentView.alpha = 1.0
}
}
@ -405,7 +405,7 @@ private extension EmulationViewController
self.sustainedInputs[ObjectIdentifier(gameController)] = []
}
func addSustainedInput(input: InputType, gameController: GameControllerProtocol)
func addSustainedInput(_ input: InputType, gameController: GameControllerProtocol)
{
var inputs = self.sustainedInputs[ObjectIdentifier(gameController)] ?? []
@ -424,10 +424,10 @@ private extension EmulationViewController
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
self.reactivateSustainInputsQueue.addOperationWithBlock {
self.reactivateSustainInputsQueue.addOperation {
// The manual activations/deactivations here are hidden implementation details, so we won't notify ourselves about them
gameController.removeReceiver(self)
@ -435,8 +435,8 @@ private extension EmulationViewController
// Must deactivate first so core recognizes a secondary activation
gameController.deactivate(input)
let dispatchQueue = dispatch_queue_create("com.rileytestut.Delta.sustainButtonsQueue", DISPATCH_QUEUE_SERIAL)
dispatch_async(dispatchQueue) {
let dispatchQueue = DispatchQueue(label: "com.rileytestut.Delta.sustainButtonsQueue", attributes: DispatchQueueAttributes.serial)
dispatchQueue.async {
let semaphore = DispatchSemaphore(value: 0)
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
// Unfortunately we cannot init DispatchSemaphore with value less than 0
// To compensate, we simply wait twice; once the first wait returns, we wait again
dispatch_semaphore_wait(semaphore.semaphore, DISPATCH_TIME_FOREVER)
dispatch_semaphore_wait(semaphore.semaphore, DISPATCH_TIME_FOREVER)
semaphore.semaphore.wait(timeout: DispatchTime.distantFuture)
semaphore.semaphore.wait(timeout: DispatchTime.distantFuture)
// 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)
@ -481,12 +481,12 @@ private extension EmulationViewController
/// Save States
extension EmulationViewController: SaveStatesViewControllerDelegate
{
func saveStatesViewControllerActiveEmulatorCore(saveStatesViewController: SaveStatesViewController) -> EmulatorCore
func saveStatesViewControllerActiveEmulatorCore(_ saveStatesViewController: SaveStatesViewController) -> 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 }
@ -495,13 +495,13 @@ extension EmulationViewController: SaveStatesViewControllerDelegate
self.emulatorCore.saveSaveState { temporarySaveState in
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
{
try NSFileManager.defaultManager().moveItemAtURL(temporarySaveState.fileURL, toURL: saveState.fileURL)
try FileManager.default.moveItem(at: temporarySaveState.fileURL, to: saveState.fileURL)
updatingExistingSaveState = false
}
@ -514,13 +514,13 @@ extension EmulationViewController: SaveStatesViewControllerDelegate
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)
UIImagePNGRepresentation(image)?.writeToURL(saveState.imageFileURL, atomically: true)
let image = UIImage(cgImage: quartzImage)
try? UIImagePNGRepresentation(image)?.write(to: saveState.imageFileURL, options: [.dataWritingAtomic])
}
saveState.modifiedDate = NSDate()
saveState.modifiedDate = Date()
// Dismiss if updating an existing save state.
// 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
{
@ -555,17 +555,17 @@ extension EmulationViewController: SaveStatesViewControllerDelegate
/// Cheats
extension EmulationViewController: CheatsViewControllerDelegate
{
func cheatsViewControllerActiveEmulatorCore(saveStatesViewController: CheatsViewController) -> EmulatorCore
func cheatsViewControllerActiveEmulatorCore(_ saveStatesViewController: CheatsViewController) -> 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)
}
func cheatsViewController(cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat)
func cheatsViewController(_ cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat)
{
self.emulatorCore.deactivateCheat(cheat)
}
@ -573,9 +573,9 @@ extension EmulationViewController: CheatsViewControllerDelegate
private func updateCheats()
{
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlockAndWait {
backgroundContext.performAndWait {
let running = (self.emulatorCore.state == .Running)
let running = (self.emulatorCore.state == .running)
if running
{
@ -583,7 +583,7 @@ extension EmulationViewController: CheatsViewControllerDelegate
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)
for cheat in cheats
@ -623,12 +623,12 @@ extension EmulationViewController: CheatsViewControllerDelegate
//MARK: - App Lifecycle -
private extension EmulationViewController
{
@objc func willResignActive(notification: NSNotification)
@objc func willResignActive(_ notification: Notification)
{
self.pauseEmulation()
}
@objc func didBecomeActive(notification: NSNotification)
@objc func didBecomeActive(_ notification: Notification)
{
self.resumeEmulation()
}
@ -638,18 +638,18 @@ private extension EmulationViewController
/// <GameControllerReceiver>
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
{
switch input
{
case ControllerInput.Menu:
case ControllerInput.menu:
if self.choosingSustainedButtons { self.hideSustainButtonView() }
self.pause(sender: gameController)
@ -667,7 +667,7 @@ extension EmulationViewController: GameControllerReceiverProtocol
if let sustainedInputs = self.sustainedInputs[ObjectIdentifier(gameController)] where sustainedInputs.contains({ $0.isEqual(input) })
{
// Perform on next run loop
dispatch_async(dispatch_get_main_queue()) {
DispatchQueue.main.async {
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 }

View File

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

View File

@ -13,6 +13,6 @@ extension UIViewController
var isPreviewing: Bool
{
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()
@ -62,14 +62,14 @@ class GamesCollectionViewController: UICollectionViewController
// MARK: - 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 -
private func configureCell(cell: GridCollectionViewCell, game: Game)
private func configureCell(_ cell: GridCollectionViewCell, game: Game)
{
cell.maximumImageSize = CGSize(width: 90, height: 90)
cell.textLabel.text = game.name
@ -79,7 +79,7 @@ class GamesCollectionViewController: UICollectionViewController
extension GamesCollectionViewController: NSFetchedResultsControllerDelegate
{
func controllerDidChangeContent(controller: NSFetchedResultsController)
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
{
self.collectionView?.reloadData()
}

View File

@ -19,16 +19,16 @@ class GamesViewController: UIViewController
private var backgroundView: RSTBackgroundView!
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")
}
required init?(coder aDecoder: NSCoder)
{
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)
@ -44,29 +44,29 @@ class GamesViewController: UIViewController
self.automaticallyAdjustsScrollViewInsets = false
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.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.dataSource = self
self.pageViewController.delegate = self
self.pageViewController.view.hidden = true
self.pageViewController.view.isHidden = true
self.pageControl = UIPageControl()
self.pageControl.translatesAutoresizingMaskIntoConstraints = false
self.pageControl.hidesForSinglePage = false
self.pageControl.numberOfPages = 3
self.pageControl.currentPageIndicatorTintColor = UIColor.purpleColor()
self.pageControl.pageIndicatorTintColor = UIColor.lightGrayColor()
self.pageControl.currentPageIndicatorTintColor = UIColor.purple()
self.pageControl.pageIndicatorTintColor = UIColor.lightGray()
self.navigationController?.toolbar.addSubview(self.pageControl)
self.pageControl.centerXAnchor.constraintEqualToAnchor(self.navigationController?.toolbar.centerXAnchor, constant: 0).active = true
self.pageControl.centerYAnchor.constraintEqualToAnchor(self.navigationController?.toolbar.centerYAnchor, constant: 0).active = true
self.pageControl.centerXAnchor.constraint(equalTo: (self.navigationController?.toolbar.centerXAnchor)!, constant: 0).isActive = 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)
@ -115,14 +115,14 @@ class GamesViewController: UIViewController
// MARK: - 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 destinationViewController = segue.destinationViewController as? EmulationViewController else { return }
guard let cell = sender as? UICollectionViewCell else { return }
let indexPath = sourceViewController.collectionView?.indexPathForCell(cell)
let game = sourceViewController.dataSource.fetchedResultsController.objectAtIndexPath(indexPath!) as! Game
let indexPath = sourceViewController.collectionView?.indexPath(for: cell)
let game = sourceViewController.dataSource.fetchedResultsController.object(at: indexPath!) as! 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
{
func viewControllerForIndex(index: Int) -> GamesCollectionViewController?
func viewControllerForIndex(_ index: Int) -> GamesCollectionViewController?
{
guard let pages = self.fetchedResultsController.sections?.first?.numberOfObjects where pages > 0 else { return nil }
@ -179,10 +179,10 @@ private extension GamesViewController
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
viewController.gameCollection = self.fetchedResultsController.objectAtIndexPath(indexPath) as! GameCollection
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "gamesCollectionViewController") as! GamesCollectionViewController
viewController.gameCollection = self.fetchedResultsController.object(at: indexPath) as! GameCollection
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
viewController.segueHandler = self
@ -198,7 +198,7 @@ private extension GamesViewController
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
}
@ -216,31 +216,31 @@ private extension GamesViewController
if sections > 0
{
// Reset page view controller if currently hidden or current child should view controller no longer exists
if self.pageViewController.view.hidden || resetPageViewController
if self.pageViewController.view.isHidden || resetPageViewController
{
if let viewController = self.viewControllerForIndex(0)
{
self.pageViewController.view.hidden = false
self.backgroundView.hidden = true
self.pageViewController.view.isHidden = false
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
}
}
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
{
self.title = NSLocalizedString("Games", comment: "")
if !self.pageViewController.view.hidden
if !self.pageViewController.view.isHidden
{
self.pageViewController.view.hidden = true
self.backgroundView.hidden = false
self.pageViewController.view.isHidden = true
self.backgroundView.isHidden = false
}
}
}
@ -248,7 +248,7 @@ private extension GamesViewController
extension GamesViewController: GamePickerControllerDelegate
{
func gamePickerController(gamePickerController: GamePickerController, didImportGames games: [Game])
func gamePickerController(_ gamePickerController: GamePickerController, didImportGames games: [Game])
{
print(games)
}
@ -256,23 +256,23 @@ extension GamesViewController: GamePickerControllerDelegate
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)
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)
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
{
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
}
@ -282,7 +282,7 @@ extension GamesViewController: UIPageViewControllerDelegate, UIPageViewControlle
extension GamesViewController: NSFetchedResultsControllerDelegate
{
func controllerDidChangeContent(controller: NSFetchedResultsController)
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
{
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)
{
@ -44,7 +44,7 @@ extension CheatTextView
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)
self.textContainer.size = CGSize(width: width, height: 0)
@ -65,13 +65,13 @@ private extension CheatTextView
let attributedFormat = NSMutableAttributedString()
var prefixString: NSString? = nil
let scanner = NSScanner(string: format)
let scanner = Scanner(string: format)
scanner.charactersToBeSkipped = nil
while (!scanner.atEnd)
while (!scanner.isAtEnd)
{
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 }
@ -82,10 +82,10 @@ private extension CheatTextView
attributedString.addAttribute(CheatPrefixAttribute, value: prefixString, range: NSRange(location: 0, length: 1))
}
attributedFormat.appendAttributedString(attributedString)
attributedFormat.append(attributedString)
prefixString = nil
scanner.scanUpToCharactersFromSet(NSCharacterSet.alphanumericCharacterSet(), intoString: &prefixString)
scanner.scanUpToCharacters(from: CharacterSet.alphanumerics, into: &prefixString)
}
self.attributedFormat = attributedFormat
@ -95,17 +95,17 @@ private extension CheatTextView
self.layoutIfNeeded()
let range = NSRange(location: 0, length: (self.text as NSString).length)
self.layoutManager.invalidateGlyphsForCharacterRange(range, changeInLength: 0, actualCharacterRange: nil)
self.layoutManager.invalidateLayoutForCharacterRange(range, actualCharacterRange: nil)
self.layoutManager.ensureGlyphsForCharacterRange(range)
self.layoutManager.ensureLayoutForCharacterRange(range)
self.layoutManager.invalidateGlyphs(forCharacterRange: range, changeInLength: 0, actualCharacterRange: nil)
self.layoutManager.invalidateLayout(forCharacterRange: range, actualCharacterRange: nil)
self.layoutManager.ensureGlyphs(forCharacterRange: range)
self.layoutManager.ensureLayout(forCharacterRange: range)
}
}
}
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
guard let attributedFormat = self.attributedFormat else { return 0 }
@ -117,9 +117,9 @@ extension CheatTextView: NSLayoutManagerDelegate
let bufferSize = max(attributedFormat.length + 1, glyphCount * 2)
// Allocate our replacement buffers
let glyphBuffer = UnsafeMutablePointer<CGGlyph>.alloc(bufferSize)
let propertyBuffer = UnsafeMutablePointer<NSGlyphProperty>.alloc(bufferSize)
let characterBuffer = UnsafeMutablePointer<Int>.alloc(bufferSize)
let glyphBuffer = UnsafeMutablePointer<CGGlyph>(allocatingCapacity: bufferSize)
let propertyBuffer = UnsafeMutablePointer<NSGlyphProperty>(allocatingCapacity: bufferSize)
let characterBuffer = UnsafeMutablePointer<Int>(allocatingCapacity: bufferSize)
var offset = 0
@ -128,7 +128,7 @@ extension CheatTextView: NSLayoutManagerDelegate
// The index the actual character maps to in the cheat format
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
let prefixCount = prefix.characters.count
@ -139,7 +139,7 @@ extension CheatTextView: NSLayoutManagerDelegate
propertyBuffer[i + offset + j] = props[i]
// 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)
}
@ -156,11 +156,11 @@ extension CheatTextView: NSLayoutManagerDelegate
layoutManager.setGlyphs(glyphBuffer, properties: propertyBuffer, characterIndexes: characterBuffer, font: aFont, forGlyphRange: NSRange(location: glyphRange.location, length: glyphCount + offset))
// Clean up memory
characterBuffer.dealloc(bufferSize)
propertyBuffer.dealloc(bufferSize)
glyphBuffer.dealloc(bufferSize)
characterBuffer.deallocateCapacity(bufferSize)
propertyBuffer.deallocateCapacity(bufferSize)
glyphBuffer.deallocateCapacity(bufferSize)
// Return total number of glyphs
return glyphCount + offset
}
}
}

View File

@ -15,9 +15,9 @@ import Roxas
protocol CheatsViewControllerDelegate: class
{
func cheatsViewControllerActiveEmulatorCore(saveStatesViewController: CheatsViewController) -> EmulatorCore
func cheatsViewController(cheatsViewController: CheatsViewController, didActivateCheat cheat: Cheat) throws
func cheatsViewController(cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat)
func cheatsViewControllerActiveEmulatorCore(_ saveStatesViewController: CheatsViewController) -> EmulatorCore
func cheatsViewController(_ cheatsViewController: CheatsViewController, didActivateCheat cheat: Cheat) throws
func cheatsViewController(_ cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat)
}
class CheatsViewController: UITableViewController
@ -30,7 +30,7 @@ class CheatsViewController: UITableViewController
private var backgroundView: RSTBackgroundView!
private var fetchedResultsController: NSFetchedResultsController!
private var fetchedResultsController: NSFetchedResultsController<AnyObject>!
}
extension CheatsViewController
@ -42,18 +42,18 @@ extension CheatsViewController
self.title = NSLocalizedString("Cheats", comment: "")
self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
self.backgroundView.hidden = false
self.backgroundView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
self.backgroundView.isHidden = false
self.backgroundView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
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.textColor = UIColor.whiteColor()
self.backgroundView.detailTextLabel.textColor = UIColor.white()
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()
@ -72,7 +72,7 @@ extension CheatsViewController
//MARK: - Navigation -
private extension CheatsViewController
{
@IBAction func unwindFromEditCheatViewController(segue: UIStoryboardSegue)
@IBAction func unwindFromEditCheatViewController(_ segue: UIStoryboardSegue)
{
}
@ -87,8 +87,8 @@ private extension CheatsViewController
let fetchRequest = Cheat.fetchRequest()
fetchRequest.returnsObjectsAsFaults = false
fetchRequest.predicate = NSPredicate(format: "%K == %@", Cheat.Attributes.game.rawValue, game)
fetchRequest.sortDescriptors = [NSSortDescriptor(key: Cheat.Attributes.name.rawValue, ascending: true)]
fetchRequest.predicate = Predicate(format: "%K == %@", Cheat.Attributes.game.rawValue, game)
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.delegate = self
@ -98,13 +98,13 @@ private extension CheatsViewController
{
if let fetchedObjects = self.fetchedResultsController.fetchedObjects where fetchedObjects.count > 0
{
self.tableView.separatorStyle = .SingleLine
self.backgroundView.hidden = true
self.tableView.separatorStyle = .singleLine
self.backgroundView.isHidden = true
}
else
{
self.tableView.separatorStyle = .None
self.backgroundView.hidden = false
self.tableView.separatorStyle = .none
self.backgroundView.isHidden = false
}
}
}
@ -119,14 +119,14 @@ private extension CheatsViewController
editCheatViewController.presentWithPresentingViewController(self)
}
func deleteCheat(cheat: Cheat)
func deleteCheat(_ cheat: Cheat)
{
self.delegate.cheatsViewController(self, didDeactivateCheat: cheat)
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlock {
let temporaryCheat = backgroundContext.objectWithID(cheat.objectID)
backgroundContext.deleteObject(temporaryCheat)
backgroundContext.perform {
let temporaryCheat = backgroundContext.object(with: cheat.objectID)
backgroundContext.delete(temporaryCheat)
backgroundContext.saveWithErrorLogging()
}
}
@ -136,17 +136,17 @@ private extension CheatsViewController
/// Convenience
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?.font = UIFont.boldSystemFontOfSize(cell.textLabel!.font.pointSize)
cell.accessoryType = cheat.enabled ? .Checkmark : .None
cell.textLabel?.font = UIFont.boldSystemFont(ofSize: cell.textLabel!.font.pointSize)
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.supportedCheatFormats = self.delegate.cheatsViewControllerActiveEmulatorCore(self).supportedCheatFormats
editCheatViewController.cheat = cheat
@ -160,21 +160,21 @@ extension CheatsViewController
{
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
override func numberOfSections(in tableView: UITableView) -> Int
{
let numberOfSections = self.fetchedResultsController.sections!.count
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]
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)
return cell
}
@ -182,13 +182,13 @@ 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()
backgroundContext.performBlockAndWait {
let temporaryCheat = backgroundContext.objectWithID(cheat.objectID) as! Cheat
backgroundContext.performAndWait {
let temporaryCheat = backgroundContext.object(with: cheat.objectID) as! Cheat
temporaryCheat.enabled = !temporaryCheat.enabled
if temporaryCheat.enabled
@ -215,18 +215,18 @@ extension CheatsViewController
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)
}
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)
editCheatViewController.presentWithPresentingViewController(self)
}
@ -234,7 +234,7 @@ extension CheatsViewController
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
}
@ -243,20 +243,20 @@ extension CheatsViewController
//MARK: - <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
let cheat = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Cheat
let cheat = self.fetchedResultsController.object(at: indexPath) as! Cheat
let editCheatViewController = self.makeEditCheatViewController(cheat: cheat)
return editCheatViewController
}
func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController)
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController)
{
let editCheatViewController = viewControllerToCommit as! EditCheatViewController
editCheatViewController.presentWithPresentingViewController(self)
@ -266,7 +266,7 @@ extension CheatsViewController: UIViewControllerPreviewingDelegate
//MARK: - <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)
@ -274,7 +274,7 @@ extension CheatsViewController: EditCheatViewControllerDelegate
{
let code = cheat.code
previousCheat.managedObjectContext?.performBlockAndWait({
previousCheat.managedObjectContext?.performAndWait({
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)
}
@ -292,7 +292,7 @@ extension CheatsViewController: EditCheatViewControllerDelegate
//MARK: - <NSFetchedResultsControllerDelegate> -
extension CheatsViewController: NSFetchedResultsControllerDelegate
{
func controllerDidChangeContent(controller: NSFetchedResultsController)
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
{
self.tableView.reloadData()
self.updateBackgroundView()

View File

@ -14,13 +14,13 @@ import Roxas
protocol EditCheatViewControllerDelegate: class
{
func editCheatViewController(editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?) throws
func editCheatViewController(editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat)
func editCheatViewController(_ editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?) throws
func editCheatViewController(_ editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat)
}
private extension EditCheatViewController
{
enum ValidationError: ErrorType
enum ValidationError: ErrorProtocol
{
case invalidCode
case duplicateName
@ -66,18 +66,18 @@ extension EditCheatViewController
var type: CheatType!
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
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
{
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.code = ""
self.mutableCheat.name = ""
@ -107,12 +107,12 @@ extension EditCheatViewController
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
}
@ -125,13 +125,13 @@ extension EditCheatViewController
self.updateSaveButtonState()
}
override func viewDidAppear(animated: Bool)
override func viewDidAppear(_ animated: Bool)
{
super.viewDidAppear(animated)
// This matters when going from peek -> pop
// Otherwise, has no effect because viewDidLayoutSubviews has already been called
if self.appearing && !self.isPreviewing
if self.isAppearing && !self.isPreviewing
{
self.nameTextField.becomeFirstResponder()
}
@ -149,7 +149,7 @@ extension EditCheatViewController
self.codeTextView.textContainer.lineFragmentPadding = 0
}
if self.appearing && !self.isPreviewing
if self.isAppearing && !self.isPreviewing
{
self.nameTextField.becomeFirstResponder()
}
@ -159,35 +159,35 @@ extension EditCheatViewController
{
guard let cheat = self.cheat else { return [] }
let copyCodeAction = UIPreviewAction(title: NSLocalizedString("Copy Code", comment: ""), style: .Default) { (action, viewController) in
UIPasteboard.generalPasteboard().string = cheat.code
let copyCodeAction = UIPreviewAction(title: NSLocalizedString("Copy Code", comment: ""), style: .default) { (action, viewController) in
UIPasteboard.general().string = cheat.code
}
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
dispatch_async(dispatch_get_main_queue()) {
DispatchQueue.main.async {
let editCheatViewController = viewController as! EditCheatViewController
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)
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlock {
let temporaryCheat = backgroundContext.objectWithID(cheat.objectID)
backgroundContext.deleteObject(temporaryCheat)
backgroundContext.perform {
let temporaryCheat = backgroundContext.object(with: cheat.objectID)
backgroundContext.delete(temporaryCheat)
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]
}
@ -198,7 +198,7 @@ extension EditCheatViewController
// 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.codeTextView.resignFirstResponder()
@ -207,19 +207,19 @@ extension EditCheatViewController
internal extension EditCheatViewController
{
func presentWithPresentingViewController(presentingViewController: UIViewController)
func presentWithPresentingViewController(_ presentingViewController: UIViewController)
{
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
presentingViewController.presentViewController(navigationController, animated: true, completion: nil)
presentingViewController.present(navigationController, animated: true, completion: nil)
}
}
private extension EditCheatViewController
{
@IBAction func updateCheatName(sender: UITextField)
@IBAction func updateCheatName(_ sender: UITextField)
{
var title = sender.text ?? ""
if title.characters.count == 0
@ -232,17 +232,17 @@ private extension EditCheatViewController
self.updateSaveButtonState()
}
@IBAction func updateCheatType(sender: UISegmentedControl)
@IBAction func updateCheatType(_ sender: UISegmentedControl)
{
self.codeTextView.cheatFormat = self.selectedCheatFormat
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
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.sizeToFit()
@ -257,12 +257,12 @@ private extension EditCheatViewController
let isValidName = !(self.nameTextField.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.type = self.selectedCheatFormat.type
@ -272,7 +272,7 @@ private extension EditCheatViewController
{
try self.validateCheat(self.mutableCheat)
self.mutableCheat.managedObjectContext?.saveWithErrorLogging()
self.performSegueWithIdentifier("unwindEditCheatSegue", sender: sender)
self.performSegue(withIdentifier: "unwindEditCheatSegue", sender: sender)
}
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 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
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)
for cheat in cheats
@ -330,26 +330,26 @@ private extension EditCheatViewController
}
}
@IBAction func textFieldDidEndEditing(sender: UITextField)
@IBAction func textFieldDidEndEditing(_ sender: UITextField)
{
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()) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .Default, handler: { action in
DispatchQueue.main.async {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: { action in
handler?()
}))
self.presentViewController(alertController, animated: true, completion: nil)
self.present(alertController, animated: true, completion: nil)
}
}
}
extension EditCheatViewController
{
override func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String?
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String?
{
switch Section(rawValue: section)!
{
@ -360,8 +360,8 @@ extension EditCheatViewController
return title
case .code:
let containsSpaces = self.selectedCheatFormat.format.containsString(" ")
let containsDashes = self.selectedCheatFormat.format.containsString("-")
let containsSpaces = self.selectedCheatFormat.format.contains(" ")
let containsDashes = self.selectedCheatFormat.format.contains("-")
switch (containsSpaces, containsDashes)
{
@ -376,7 +376,7 @@ extension EditCheatViewController
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() }
@ -392,8 +392,8 @@ extension EditCheatViewController: UITextViewDelegate
// 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
let attributedString = NSAttributedString(string: sanitizedText, attributes: textView.typingAttributes)
textView.textStorage.replaceCharactersInRange(range, withAttributedString: attributedString)
let attributedString = AttributedString(string: sanitizedText, attributes: textView.typingAttributes)
textView.textStorage.replaceCharacters(in: range, with: attributedString)
// 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)

View File

@ -12,11 +12,11 @@ struct PauseItem: Equatable
{
let image: UIImage
let text: String
let action: (PauseItem -> Void)
let action: ((PauseItem) -> Void)
var selected = false
init(image: UIImage, text: String, action: (PauseItem -> Void))
init(image: UIImage, text: String, action: ((PauseItem) -> Void))
{
self.image = image
self.text = text
@ -27,4 +27,4 @@ struct PauseItem: Equatable
func ==(lhs: PauseItem, rhs: PauseItem) -> Bool
{
return (lhs.image == rhs.image) && (lhs.text == rhs.text)
}
}

View File

@ -27,11 +27,11 @@ class PauseMenuViewController: UICollectionViewController
override var preferredContentSize: CGSize {
set { }
get { return self.collectionView?.contentSize ?? CGSizeZero }
get { return self.collectionView?.contentSize ?? CGSize.zero }
}
private var prototypeCell = GridCollectionViewCell()
private var previousIndexPath: NSIndexPath? = nil
private var previousIndexPath: IndexPath? = nil
}
extension PauseMenuViewController
@ -45,16 +45,16 @@ extension PauseMenuViewController
collectionViewLayout.usesEqualHorizontalSpacingDistributionForSingleRow = true
// 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)
if let indexPath = self.previousIndexPath
{
UIView.animateWithDuration(0.2) {
UIView.animate(withDuration: 0.2) {
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
}
}
@ -63,54 +63,54 @@ 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.imageView.image = pauseItem.image
cell.imageView.contentMode = .Center
cell.imageView.contentMode = .center
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.textLabel.text = pauseItem.text
cell.textLabel.textColor = UIColor.whiteColor()
cell.textLabel.textColor = UIColor.white()
if pauseItem.selected
{
cell.imageView.tintColor = UIColor.blackColor()
cell.imageView.backgroundColor = UIColor.whiteColor()
cell.imageView.tintColor = UIColor.black()
cell.imageView.backgroundColor = UIColor.white()
}
else
{
cell.imageView.tintColor = UIColor.whiteColor()
cell.imageView.backgroundColor = UIColor.clearColor()
cell.imageView.tintColor = UIColor.white()
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
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)
}
}
extension PauseMenuViewController
{
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
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)
return cell
}
@ -118,34 +118,34 @@ extension PauseMenuViewController
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)
let size = self.prototypeCell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
let size = self.prototypeCell.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
return size
}
}
extension PauseMenuViewController
{
override func collectionView(collectionView: UICollectionView, didHighlightItemAtIndexPath indexPath: NSIndexPath)
override func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath)
{
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
}
override func collectionView(collectionView: UICollectionView, didUnhighlightItemAtIndexPath indexPath: NSIndexPath)
override func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath)
{
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
}
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
self.previousIndexPath = indexPath
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
let pauseItem = self.items[indexPath.item]
let pauseItem = self.items[(indexPath as NSIndexPath).item]
pauseItem.action(pauseItem)
}
}

View File

@ -17,7 +17,7 @@ class PauseViewController: UIViewController, PauseInfoProvidable
var pauseText: String? = nil
private weak var saveStatesViewControllerDelegate: SaveStatesViewControllerDelegate?
private var saveStatesViewControllerMode = SaveStatesViewController.Mode.Saving
private var saveStatesViewControllerMode = SaveStatesViewController.Mode.saving
private weak var cheatsViewControllerDelegate: CheatsViewControllerDelegate?
@ -26,7 +26,7 @@ class PauseViewController: UIViewController, PauseInfoProvidable
set { }
get
{
var preferredContentSize = self.pauseNavigationController.topViewController?.preferredContentSize ?? CGSizeZero
var preferredContentSize = self.pauseNavigationController.topViewController?.preferredContentSize ?? CGSize.zero
if preferredContentSize.height > 0
{
preferredContentSize.height += self.pauseNavigationController.navigationBar.bounds.height
@ -57,7 +57,7 @@ extension PauseViewController
override func preferredStatusBarStyle() -> UIStatusBarStyle
{
return .LightContent
return .lightContent
}
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)
}
override func targetViewControllerForAction(action: Selector, sender: AnyObject?) -> UIViewController? {
override func targetViewController(forAction action: Selector, sender: AnyObject?) -> UIViewController? {
return self.pauseNavigationController
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
{
switch segue.identifier ?? ""
{
@ -80,7 +80,7 @@ extension PauseViewController
self.pauseNavigationController = segue.destinationViewController as! UINavigationController
self.pauseNavigationController.delegate = self
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
pauseMenuViewController.items = self.items
@ -106,31 +106,31 @@ extension PauseViewController
{
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.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.performSegueWithIdentifier("cheats", sender: self)
self.performSegue(withIdentifier: "cheats", sender: self)
}
}
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!)
transitionCoordinator.presenting = (operation == .Push)
transitionCoordinator.presenting = (operation == .push)
return transitionCoordinator
}
}
}

View File

@ -25,14 +25,14 @@ class PausePresentationController: UIPresentationController
@IBOutlet private weak var pauseIconImageView: UIImageView!
@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.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
@ -44,7 +44,7 @@ class PausePresentationController: UIPresentationController
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)
}
else
@ -71,22 +71,22 @@ class PausePresentationController: UIPresentationController
}
self.blurringView.frame = self.containerView!.frame
self.blurringView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
self.blurringView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.containerView?.addSubview(self.blurringView)
self.vibrancyView.frame = self.containerView!.frame
self.vibrancyView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
self.vibrancyView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.containerView?.addSubview(self.vibrancyView)
self.contentView.alpha = 0.0
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.vibrancyView.effect = UIVibrancyEffect(forBlurEffect: blurEffect)
self.vibrancyView.effect = UIVibrancyEffect(blurEffect: blurEffect)
self.contentView.alpha = 1.0
@ -95,22 +95,22 @@ class PausePresentationController: UIPresentationController
override func dismissalTransitionWillBegin()
{
self.presentingViewController.transitionCoordinator()?.animateAlongsideTransition({ context in
self.presentingViewController.transitionCoordinator()?.animate(alongsideTransition: { context in
self.blurringView.effect = nil
self.vibrancyView.effect = nil
self.contentView.alpha = 0.0
}, completion: nil)
}
override func dismissalTransitionDidEnd(completed: Bool)
override func dismissalTransitionDidEnd(_ completed: Bool)
{
self.blurringView.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
// 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()
// 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)
// Layout content view
@ -163,7 +163,7 @@ class PausePresentationController: UIPresentationController
self.presentedView()?.frame = self.frameOfPresentedViewInContainerView()
// 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)
@ -173,11 +173,11 @@ class PausePresentationController: UIPresentationController
let currentScaleFactor = self.pauseLabel.currentScaleFactor
if currentScaleFactor < self.pauseLabel.minimumScaleFactor || CGFloatEqualToFloat(currentScaleFactor, self.pauseLabel.minimumScaleFactor)
{
self.pauseIconImageView.hidden = true
self.pauseIconImageView.isHidden = true
}
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)

View File

@ -29,17 +29,17 @@ class SaveStatesCollectionHeaderView: UICollectionReusableView
private func initialize()
{
self.textLabel.translatesAutoresizingMaskIntoConstraints = false
self.textLabel.textColor = UIColor.whiteColor()
self.textLabel.textColor = UIColor.white()
var fontDescriptor = UIFontDescriptor.preferredFontDescriptorWithTextStyle(UIFontTextStyleTitle3)
fontDescriptor = fontDescriptor.fontDescriptorWithSymbolicTraits([.TraitBold])
var fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: UIFontTextStyleTitle3)
fontDescriptor = fontDescriptor.withSymbolicTraits([.traitBold])!
self.textLabel.font = UIFont(descriptor: fontDescriptor, size: 0.0)
self.textLabel.textAlignment = .Center
self.textLabel.textAlignment = .center
self.addSubview(self.textLabel)
// Auto Layout
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[textLabel]-20-|", options: [], metrics: nil, views: ["textLabel": self.textLabel]))
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-10-[textLabel]|", options: [], metrics: nil, views: ["textLabel": self.textLabel]))
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "H:|-20-[textLabel]-20-|", 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
{
func saveStatesViewControllerActiveEmulatorCore(saveStatesViewController: SaveStatesViewController) -> EmulatorCore
func saveStatesViewController(saveStatesViewController: SaveStatesViewController, updateSaveState saveState: SaveState)
func saveStatesViewController(saveStatesViewController: SaveStatesViewController, loadSaveState saveState: SaveStateType)
func saveStatesViewControllerActiveEmulatorCore(_ saveStatesViewController: SaveStatesViewController) -> EmulatorCore
func saveStatesViewController(_ saveStatesViewController: SaveStatesViewController, updateSaveState saveState: SaveState)
func saveStatesViewController(_ saveStatesViewController: SaveStatesViewController, loadSaveState saveState: SaveStateType)
}
extension SaveStatesViewController
{
enum Mode
{
case Saving
case Loading
case saving
case loading
}
enum Section: Int
{
case Auto
case General
case Locked
case auto
case general
case locked
}
}
@ -43,7 +43,7 @@ class SaveStatesViewController: UICollectionViewController
}
}
var mode = Mode.Saving
var mode = Mode.saving
private var backgroundView: RSTBackgroundView!
@ -51,21 +51,21 @@ class SaveStatesViewController: UICollectionViewController
private var prototypeCellWidthConstraint: NSLayoutConstraint!
private var prototypeHeader = SaveStatesCollectionHeaderView()
private var fetchedResultsController: NSFetchedResultsController!
private var fetchedResultsController: NSFetchedResultsController<AnyObject>!
private let imageOperationQueue = RSTOperationQueue()
private let imageCache = NSCache()
private let imageCache = Cache()
private var currentGameState: SaveStateType?
private var selectedSaveState: SaveState?
private let dateFormatter: NSDateFormatter
private let dateFormatter: DateFormatter
required init?(coder aDecoder: NSCoder)
{
self.dateFormatter = NSDateFormatter()
self.dateFormatter.timeStyle = .ShortStyle
self.dateFormatter.dateStyle = .ShortStyle
self.dateFormatter = DateFormatter()
self.dateFormatter.timeStyle = .short
self.dateFormatter.dateStyle = .short
super.init(coder: aDecoder)
}
@ -78,16 +78,16 @@ extension SaveStatesViewController
super.viewDidLoad()
self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
self.backgroundView.hidden = true
self.backgroundView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
self.backgroundView.isHidden = true
self.backgroundView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.backgroundView.textLabel.text = NSLocalizedString("No Save States", comment: "")
self.backgroundView.textLabel.textColor = UIColor.whiteColor()
self.backgroundView.detailTextLabel.textColor = UIColor.whiteColor()
self.view.insertSubview(self.backgroundView, atIndex: 0)
self.backgroundView.textLabel.textColor = UIColor.white()
self.backgroundView.detailTextLabel.textColor = UIColor.white()
self.view.insertSubview(self.backgroundView, at: 0)
let collectionViewLayout = self.collectionViewLayout as! GridCollectionViewLayout
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
// We'll keep the same size for landscape orientation, which will allow more to fit
@ -95,29 +95,29 @@ extension SaveStatesViewController
switch self.mode
{
case .Saving:
case .saving:
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: "")
case .Loading:
case .loading:
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.navigationItem.rightBarButtonItem = nil
}
// Manually update prototype cell properties
self.prototypeCellWidthConstraint = self.prototypeCell.contentView.widthAnchor.constraintEqualToConstant(collectionViewLayout.itemWidth)
self.prototypeCellWidthConstraint.active = true
self.prototypeCellWidthConstraint = self.prototypeCell.contentView.widthAnchor.constraint(equalToConstant: collectionViewLayout.itemWidth)
self.prototypeCellWidthConstraint.isActive = true
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(SaveStatesViewController.handleLongPressGesture(_:)))
self.collectionView?.addGestureRecognizer(longPressGestureRecognizer)
self.registerForPreviewingWithDelegate(self, sourceView: self.collectionView!)
self.registerForPreviewing(with: self, sourceView: self.collectionView!)
self.updateBackgroundView()
}
override func viewWillAppear(animated: Bool)
override func viewWillAppear(_ animated: Bool)
{
self.fetchedResultsController.performFetchIfNeeded()
@ -126,7 +126,7 @@ extension SaveStatesViewController
super.viewWillAppear(animated)
}
override func viewDidDisappear(animated: Bool)
override func viewDidDisappear(_ animated: Bool)
{
super.viewDidDisappear(animated)
@ -149,8 +149,8 @@ private extension SaveStatesViewController
let fetchRequest = SaveState.fetchRequest()
fetchRequest.returnsObjectsAsFaults = false
fetchRequest.predicate = NSPredicate(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.predicate = Predicate(format: "%K == %@", SaveState.Attributes.game.rawValue, game)
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.delegate = self
@ -160,21 +160,21 @@ private extension SaveStatesViewController
{
if let fetchedObjects = self.fetchedResultsController.fetchedObjects where fetchedObjects.count > 0
{
self.backgroundView.hidden = true
self.backgroundView.isHidden = true
}
else
{
self.backgroundView.hidden = false
self.backgroundView.isHidden = false
}
}
//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")
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
if self.appearing
if self.isAppearing
{
imageOperation.immediate = true
imageOperation.isImmediate = true
}
self.imageOperationQueue.addOperation(imageOperation, forKey: indexPath)
}
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.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
cell.textLabel.textColor = UIColor.white()
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
}
func configureCollectionViewHeaderView(headerView: SaveStatesCollectionHeaderView, forSection section: Int)
func configureCollectionViewHeaderView(_ headerView: SaveStatesCollectionHeaderView, forSection section: Int)
{
let section = self.correctedSectionForSectionIndex(section)
@ -217,9 +217,9 @@ private extension SaveStatesViewController
switch section
{
case .Auto: title = NSLocalizedString("Auto Save", comment: "")
case .General: title = NSLocalizedString("General", comment: "")
case .Locked: title = NSLocalizedString("Locked", comment: "")
case .auto: title = NSLocalizedString("Auto Save", comment: "")
case .general: title = NSLocalizedString("General", comment: "")
case .locked: title = NSLocalizedString("Locked", comment: "")
}
headerView.textLabel.text = title
@ -227,15 +227,15 @@ private extension SaveStatesViewController
//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 }
for action in actions
@ -243,7 +243,7 @@ private extension SaveStatesViewController
alertController.addAction(action)
}
self.presentViewController(alertController, animated: true, completion: nil)
self.present(alertController, animated: true, completion: nil)
}
//MARK: - Save States -
@ -251,10 +251,10 @@ private extension SaveStatesViewController
@IBAction func addSaveState()
{
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlock {
backgroundContext.perform {
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)
saveState.game = game
@ -263,17 +263,17 @@ private extension SaveStatesViewController
}
}
func updateSaveState(saveState: SaveState)
func updateSaveState(_ saveState: SaveState)
{
self.delegate?.saveStatesViewController(self, updateSaveState: saveState)
saveState.managedObjectContext?.saveWithErrorLogging()
}
func loadSaveState(saveState: SaveState)
func loadSaveState(_ saveState: SaveState)
{
let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self)
if emulatorCore.state == .Stopped
if emulatorCore.state == .stopped
{
emulatorCore.startEmulation()
emulatorCore.pauseEmulation()
@ -282,47 +282,47 @@ private extension SaveStatesViewController
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)
confirmationAlertController.addAction(UIAlertAction(title: NSLocalizedString("Delete", comment: ""), style: .Default, handler: { action in
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
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlock {
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID)
backgroundContext.deleteObject(temporarySaveState)
backgroundContext.perform {
let temporarySaveState = backgroundContext.object(with: saveState.objectID)
backgroundContext.delete(temporarySaveState)
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
let alertController = UIAlertController(title: NSLocalizedString("Rename Save State", comment: ""), message: nil, preferredStyle: .Alert)
alertController.addTextFieldWithConfigurationHandler { (textField) in
let alertController = UIAlertController(title: NSLocalizedString("Rename Save State", comment: ""), message: nil, preferredStyle: .alert)
alertController.addTextField { (textField) in
textField.text = saveState.name
textField.placeholder = NSLocalizedString("Name", comment: "")
textField.autocapitalizationType = .Words
textField.returnKeyType = .Done
textField.addTarget(self, action: #selector(SaveStatesViewController.updateSaveStateName(_:)), forControlEvents: .EditingDidEnd)
textField.autocapitalizationType = .words
textField.returnKeyType = .done
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
}))
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.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 }
@ -334,9 +334,9 @@ private extension SaveStatesViewController
}
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
backgroundContext.saveWithErrorLogging()
@ -345,21 +345,21 @@ private extension SaveStatesViewController
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)
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil))
alertController.addAction(UIAlertAction(title: NSLocalizedString("Change", comment: ""), style: .Default, handler: { (action) in
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("Change", comment: ""), style: .default, handler: { (action) in
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlock {
backgroundContext.perform {
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
{
let previewSaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState
let previewSaveState = backgroundContext.object(with: saveState.objectID) as! SaveState
game.previewSaveState = previewSaveState
}
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()
backgroundContext.performBlockAndWait() {
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState
temporarySaveState.type = .Locked
backgroundContext.performAndWait() {
let temporarySaveState = backgroundContext.object(with: saveState.objectID) as! SaveState
temporarySaveState.type = .locked
backgroundContext.saveWithErrorLogging()
}
}
func unlockSaveState(saveState: SaveState)
func unlockSaveState(_ saveState: SaveState)
{
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlockAndWait() {
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState
temporarySaveState.type = .General
backgroundContext.performAndWait() {
let temporarySaveState = backgroundContext.object(with: saveState.objectID) as! SaveState
temporarySaveState.type = .general
backgroundContext.saveWithErrorLogging()
}
}
@ -406,7 +406,7 @@ private extension SaveStatesViewController
// Remove temporary save state file
do
{
try NSFileManager.defaultManager().removeItemAtURL(saveState.fileURL)
try FileManager.default.removeItem(at: saveState.fileURL)
}
catch let error as NSError
{
@ -447,7 +447,7 @@ private extension SaveStatesViewController
//MARK: - Convenience Methods -
func correctedSectionForSectionIndex(section: Int) -> Section
func correctedSectionForSectionIndex(_ section: Int) -> Section
{
let sectionInfo = self.fetchedResultsController.sections![section]
let sectionIndex = Int(sectionInfo.name)!
@ -456,53 +456,53 @@ private extension SaveStatesViewController
return section
}
func actionsForSaveState(saveState: SaveState) -> [Action]
func actionsForSaveState(_ saveState: SaveState) -> [Action]
{
var actions = [Action]()
if self.traitCollection.forceTouchCapability == .Available
if self.traitCollection.forceTouchCapability == .available
{
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)
})
actions.append(previewAction)
}
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)
})
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)
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)
})
actions.append(renameAction)
switch saveState.type
{
case .Auto: break
case .General:
let lockAction = Action(title: NSLocalizedString("Lock", comment: ""), style: .Default, action: { action in
case .auto: break
case .general:
let lockAction = Action(title: NSLocalizedString("Lock", comment: ""), style: .default, action: { action in
self.lockSaveState(saveState)
})
actions.append(lockAction)
case .Locked:
let unlockAction = Action(title: NSLocalizedString("Unlock", comment: ""), style: .Default, action: { action in
case .locked:
let unlockAction = Action(title: NSLocalizedString("Unlock", comment: ""), style: .default, action: { action in
self.unlockSaveState(saveState)
})
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)
})
actions.append(deleteAction)
@ -514,20 +514,20 @@ private extension SaveStatesViewController
//MARK: - <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
let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self)
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.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
// 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
let fileURL = NSFileManager.uniqueTemporaryURL()
let fileURL = FileManager.uniqueTemporaryURL()
do
{
try NSFileManager.defaultManager().moveItemAtURL(saveState.fileURL, toURL: fileURL)
try FileManager.default.moveItem(at: saveState.fileURL, to: fileURL)
}
catch let error as NSError
{
@ -572,7 +572,7 @@ extension SaveStatesViewController: UIViewControllerPreviewingDelegate
return emulationViewController
}
func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController)
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController)
{
let emulationViewController = viewControllerToCommit as! EmulationViewController
@ -598,29 +598,29 @@ extension SaveStatesViewController: UIViewControllerPreviewingDelegate
//MARK: - <UICollectionViewDataSource> -
extension SaveStatesViewController
{
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
override func numberOfSections(in collectionView: UICollectionView) -> Int
{
let numberOfSections = self.fetchedResultsController.sections!.count
return numberOfSections
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
let section = self.fetchedResultsController.sections![section]
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)
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
self.configureCollectionViewHeaderView(headerView, forSection: indexPath.section)
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Header", for: indexPath) as! SaveStatesCollectionHeaderView
self.configureCollectionViewHeaderView(headerView, forSection: (indexPath as NSIndexPath).section)
return headerView
}
}
@ -628,39 +628,39 @@ extension SaveStatesViewController
//MARK: - <UICollectionViewDelegate> -
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
{
case .Saving:
case .saving:
let section = self.correctedSectionForSectionIndex(indexPath.section)
let section = self.correctedSectionForSectionIndex((indexPath as NSIndexPath).section)
switch section
{
case .Auto: break
case .General:
case .auto: break
case .general:
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlockAndWait() {
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState
backgroundContext.performAndWait() {
let temporarySaveState = backgroundContext.object(with: saveState.objectID) as! SaveState
self.updateSaveState(temporarySaveState)
}
case .Locked:
let alertController = UIAlertController(title: NSLocalizedString("Cannot Modify Locked Save State", comment: ""), message: NSLocalizedString("This save state must first be unlocked before it can be modified.", comment: ""), preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .Cancel, handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
case .locked:
let alertController = UIAlertController(title: NSLocalizedString("Cannot Modify Locked Save State", comment: ""), message: NSLocalizedString("This save state must first be unlocked before it can be modified.", comment: ""), preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .cancel, handler: nil))
self.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()
}
}
@ -668,20 +668,20 @@ extension SaveStatesViewController
//MARK: - <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
self.configureCollectionViewCell(self.prototypeCell, forIndexPath: indexPath, ignoreExpensiveOperations: true)
let size = self.prototypeCell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
let size = self.prototypeCell.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
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)
let size = self.prototypeHeader.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
let size = self.prototypeHeader.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
return size
}
}
@ -689,9 +689,9 @@ extension SaveStatesViewController: UICollectionViewDelegateFlowLayout
//MARK: - <NSFetchedResultsControllerDelegate> -
extension SaveStatesViewController: NSFetchedResultsControllerDelegate
{
func controllerDidChangeContent(controller: NSFetchedResultsController)
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
{
self.collectionView?.reloadData()
self.updateBackgroundView()
}
}
}

View File

@ -22,7 +22,7 @@ class PauseStoryboardSegue: UIStoryboardSegue
override func perform()
{
self.destinationViewController.transitioningDelegate = self
self.destinationViewController.modalPresentationStyle = .Custom
self.destinationViewController.modalPresentationStyle = .custom
self.destinationViewController.modalPresentationCapturesStatusBarAppearance = true
super.perform()
@ -31,17 +31,17 @@ class PauseStoryboardSegue: UIStoryboardSegue
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
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?
{
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
}
@ -49,20 +49,20 @@ extension PauseStoryboardSegue: UIViewControllerTransitioningDelegate
extension PauseStoryboardSegue: UIViewControllerAnimatedTransitioning
{
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval
{
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.origin.y = transitionContext.containerView()!.bounds.height
transitionContext.containerView()!.addSubview(destinationViewController.view)
destinationViewController.view.frame = transitionContext.finalFrame(for: destinationViewController)
destinationViewController.view.frame.origin.y = transitionContext.containerView().bounds.height
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
// Additionally, if it's animated, it looks weird

View File

@ -21,25 +21,25 @@ class PauseTransitionCoordinator: NSObject, UIViewControllerAnimatedTransitionin
super.init()
}
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval
{
return 0.4
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning)
func animateTransition(using transitionContext: UIViewControllerContextTransitioning)
{
let destinationViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
let sourceViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
let destinationViewController = transitionContext.viewController(forKey: UITransitionContextToViewControllerKey)!
let sourceViewController = transitionContext.viewController(forKey: UITransitionContextFromViewControllerKey)!
destinationViewController.view.frame = transitionContext.finalFrameForViewController(destinationViewController)
destinationViewController.view.frame.origin.y = self.presenting ? transitionContext.containerView()!.bounds.height : -destinationViewController.view.bounds.height
transitionContext.containerView()!.addSubview(destinationViewController.view)
destinationViewController.view.frame = transitionContext.finalFrame(for: destinationViewController)
destinationViewController.view.frame.origin.y = self.presenting ? transitionContext.containerView().bounds.height : -destinationViewController.view.bounds.height
transitionContext.containerView().addSubview(destinationViewController.view)
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
self.presentationController.containerView?.setNeedsLayout()

View File

@ -11,15 +11,15 @@ import DeltaCore
private enum ControllersSettingsSection: Int
{
case None
case LocalDevice
case ExternalControllers
case none
case localDevice
case externalControllers
}
private class LocalDeviceController: ExternalController
{
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 = {
let device = LocalDeviceController()
@ -52,8 +52,8 @@ class ControllersSettingsViewController: UITableViewController
{
super.init(coder: aDecoder)
NSNotificationCenter.defaultCenter().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.externalControllerDidConnect(_:)), name: ExternalControllerDidConnectNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ControllersSettingsViewController.externalControllerDidDisconnect(_:)), name: ExternalControllerDidDisconnectNotification, object: nil)
}
override func viewDidLoad()
@ -63,7 +63,7 @@ class ControllersSettingsViewController: UITableViewController
//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 }
@ -71,18 +71,18 @@ class ControllersSettingsViewController: UITableViewController
controllers.append(self.localDeviceController)
// 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]
controller.playerIndex = nil
}
switch ControllersSettingsSection(rawValue: indexPath.section)!
switch ControllersSettingsSection(rawValue: (indexPath as NSIndexPath).section)!
{
case .None: break
case .LocalDevice: self.localDeviceController.playerIndex = self.playerIndex
case .ExternalControllers:
let controller = self.connectedControllers[indexPath.row]
case .none: break
case .localDevice: self.localDeviceController.playerIndex = self.playerIndex
case .externalControllers:
let controller = self.connectedControllers[(indexPath as NSIndexPath).row]
controller.playerIndex = self.playerIndex
}
@ -93,60 +93,60 @@ class ControllersSettingsViewController: UITableViewController
private extension ControllersSettingsViewController
{
dynamic func externalControllerDidConnect(notification: NSNotification)
dynamic func externalControllerDidConnect(_ notification: Notification)
{
guard let controller = notification.object as? ExternalController else { return }
if let playerIndex = controller.playerIndex
{
self.connectedControllers.insert(controller, atIndex: playerIndex)
self.connectedControllers.insert(controller, at: playerIndex)
}
else
{
self.connectedControllers.append(controller)
}
if let index = self.connectedControllers.indexOf(controller)
if let index = self.connectedControllers.index(of: controller)
{
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
{
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 }
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
{
self.tableView.deleteSections(NSIndexSet(index: ControllersSettingsSection.ExternalControllers.rawValue), withRowAnimation: .Fade)
self.tableView.deleteSections(IndexSet(integer: ControllersSettingsSection.externalControllers.rawValue), with: .fade)
}
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
{
self.tableView.reloadSections(NSIndexSet(index: ControllersSettingsSection.None.rawValue), withRowAnimation: .None)
self.tableView.reloadSections(IndexSet(integer: ControllersSettingsSection.none.rawValue), with: .none)
}
}
}
extension ControllersSettingsViewController
{
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
override func numberOfSections(in tableView: UITableView) -> Int
{
if self.connectedControllers.count == 0
{
@ -156,42 +156,42 @@ extension ControllersSettingsViewController
return 3
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
switch ControllersSettingsSection(rawValue: section)!
{
case .None: return 1
case .LocalDevice: return 1
case .ExternalControllers: return self.connectedControllers.count
case .none: return 1
case .localDevice: return 1
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.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: "")
if Settings.localControllerPlayerIndex != self.playerIndex && !self.connectedControllers.contains({ $0.playerIndex == self.playerIndex })
{
cell.accessoryType = .Checkmark
cell.accessoryType = .checkmark
}
}
else
{
let controller: ExternalController
if indexPath.section == ControllersSettingsSection.LocalDevice.rawValue
if (indexPath as NSIndexPath).section == ControllersSettingsSection.localDevice.rawValue
{
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
{
@ -202,7 +202,7 @@ extension ControllersSettingsViewController
if controller.playerIndex == self.playerIndex
{
cell.accessoryType = .Checkmark
cell.accessoryType = .checkmark
}
else
{
@ -217,13 +217,13 @@ extension ControllersSettingsViewController
return cell
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String?
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
{
switch ControllersSettingsSection(rawValue: section)!
{
case .None: return nil
case .LocalDevice: return NSLocalizedString("Local Device", comment: "")
case .ExternalControllers: return self.connectedControllers.count > 0 ? NSLocalizedString("External Controllers", comment: "") : ""
case .none: return nil
case .localDevice: return NSLocalizedString("Local Device", comment: "")
case .externalControllers: return self.connectedControllers.count > 0 ? NSLocalizedString("External Controllers", comment: "") : ""
}
}
}

View File

@ -11,7 +11,7 @@ import DeltaCore
private enum SettingsSection: Int
{
case Controllers
case controllers
}
private enum SettingsSegues: String
@ -25,8 +25,8 @@ class SettingsViewController: UITableViewController
{
super.init(coder: aDecoder)
NSNotificationCenter.defaultCenter().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.externalControllerDidConnect(_:)), name: ExternalControllerDidConnectNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(SettingsViewController.externalControllerDidDisconnect(_:)), name: ExternalControllerDidDisconnectNotification, object: nil)
}
override func viewDidLoad()
@ -34,13 +34,13 @@ class SettingsViewController: UITableViewController
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool)
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
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()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == SettingsSegues.Controllers.rawValue
{
let controllersSettingsViewController = segue.destinationViewController as! ControllersSettingsViewController
controllersSettingsViewController.playerIndex = self.tableView.indexPathForSelectedRow?.row
controllersSettingsViewController.playerIndex = (self.tableView.indexPathForSelectedRow as NSIndexPath?)?.row
}
}
}
private extension SettingsViewController
{
@IBAction func unwindFromControllersSettingsViewController(segue: UIStoryboardSegue)
@IBAction func unwindFromControllersSettingsViewController(_ segue: UIStoryboardSegue)
{
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
{
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
{
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]
cell.detailTextLabel?.text = controller.name
@ -110,11 +110,11 @@ extension SettingsViewController
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 = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700;
TargetAttributes = {
0A60B5C71D5A2CFF92811AA9AEC27278 = {
LastSwiftMigration = 0800;
};
B20CFA992EEA3E3A903F2359B05A88E1 = {
LastSwiftMigration = 0800;
};
};
};
buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */;
compatibilityVersion = "Xcode 3.2";
@ -303,6 +311,7 @@
PRODUCT_NAME = Pods;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TVOS_DEPLOYMENT_TARGET = 9.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -328,6 +337,7 @@
PRODUCT_NAME = FileMD5Hash;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TVOS_DEPLOYMENT_TARGET = 9.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -353,6 +363,7 @@
PRODUCT_NAME = FileMD5Hash;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TVOS_DEPLOYMENT_TARGET = 9.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -420,6 +431,7 @@
PRODUCT_NAME = Pods;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TVOS_DEPLOYMENT_TARGET = 9.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";