Updates syntax to Swift 3 beta 2 via Xcode migrator
This commit is contained in:
parent
e6585ec177
commit
9ce16a2a9d
@ -46,23 +46,23 @@ class GameCollectionViewDataSource: NSObject
|
|||||||
|
|
||||||
let fetchRequest = Game.fetchRequest()
|
let fetchRequest = Game.fetchRequest()
|
||||||
|
|
||||||
var predicates: [NSPredicate] = []
|
var predicates: [Predicate] = []
|
||||||
|
|
||||||
if let identifiers = self.supportedGameCollectionIdentifiers
|
if let identifiers = self.supportedGameCollectionIdentifiers
|
||||||
{
|
{
|
||||||
for identifier in identifiers
|
for identifier in identifiers
|
||||||
{
|
{
|
||||||
let predicate = NSPredicate(format: "SUBQUERY(%K, $x, $x.%K == %@).@count > 0", Game.Attributes.gameCollections.rawValue, GameCollection.Attributes.identifier.rawValue, identifier)
|
let predicate = Predicate(format: "SUBQUERY(%K, $x, $x.%K == %@).@count > 0", Game.Attributes.gameCollections.rawValue, GameCollection.Attributes.identifier.rawValue, identifier)
|
||||||
predicates.append(predicate)
|
predicates.append(predicate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if predicates.count > 0
|
if predicates.count > 0
|
||||||
{
|
{
|
||||||
fetchRequest.predicate = NSCompoundPredicate(orPredicateWithSubpredicates: predicates)
|
fetchRequest.predicate = CompoundPredicate(orPredicateWithSubpredicates: predicates)
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: Game.Attributes.typeIdentifier.rawValue, ascending: true), NSSortDescriptor(key: Game.Attributes.name.rawValue, ascending: true)]
|
fetchRequest.sortDescriptors = [SortDescriptor(key: Game.Attributes.typeIdentifier.rawValue, ascending: true), SortDescriptor(key: Game.Attributes.name.rawValue, ascending: true)]
|
||||||
|
|
||||||
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: Game.Attributes.typeIdentifier.rawValue, cacheName: nil)
|
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: Game.Attributes.typeIdentifier.rawValue, cacheName: nil)
|
||||||
self.fetchedResultsController.delegate = previousDelegate
|
self.fetchedResultsController.delegate = previousDelegate
|
||||||
@ -72,9 +72,9 @@ class GameCollectionViewDataSource: NSObject
|
|||||||
|
|
||||||
// MARK: - Collection View -
|
// MARK: - Collection View -
|
||||||
|
|
||||||
private func configureCell(cell: GridCollectionViewCell, forIndexPath indexPath: NSIndexPath)
|
private func configureCell(_ cell: GridCollectionViewCell, forIndexPath indexPath: IndexPath)
|
||||||
{
|
{
|
||||||
let game = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Game
|
let game = self.fetchedResultsController.object(at: indexPath) as! Game
|
||||||
|
|
||||||
if let handler = self.cellConfigurationHandler
|
if let handler = self.cellConfigurationHandler
|
||||||
{
|
{
|
||||||
@ -85,20 +85,20 @@ class GameCollectionViewDataSource: NSObject
|
|||||||
|
|
||||||
extension GameCollectionViewDataSource: UICollectionViewDataSource
|
extension GameCollectionViewDataSource: UICollectionViewDataSource
|
||||||
{
|
{
|
||||||
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
|
func numberOfSections(in collectionView: UICollectionView) -> Int
|
||||||
{
|
{
|
||||||
return self.fetchedResultsController.sections?.count ?? 0
|
return self.fetchedResultsController.sections?.count ?? 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
|
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
|
||||||
{
|
{
|
||||||
let count = self.fetchedResultsController.sections?[section].numberOfObjects ?? 0
|
let count = self.fetchedResultsController.sections?[section].numberOfObjects ?? 0
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
|
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
|
||||||
{
|
{
|
||||||
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("GameCell", forIndexPath: indexPath) as! GridCollectionViewCell
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "GameCell", for: indexPath) as! GridCollectionViewCell
|
||||||
|
|
||||||
self.configureCell(cell, forIndexPath: indexPath)
|
self.configureCell(cell, forIndexPath: indexPath)
|
||||||
|
|
||||||
@ -108,18 +108,18 @@ extension GameCollectionViewDataSource: UICollectionViewDataSource
|
|||||||
|
|
||||||
extension GameCollectionViewDataSource: UICollectionViewDelegate
|
extension GameCollectionViewDataSource: UICollectionViewDelegate
|
||||||
{
|
{
|
||||||
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
|
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize
|
||||||
{
|
{
|
||||||
let collectionViewLayout = collectionView.collectionViewLayout as! GridCollectionViewLayout
|
let collectionViewLayout = collectionView.collectionViewLayout as! GridCollectionViewLayout
|
||||||
|
|
||||||
let widthConstraint = self.prototypeCell.contentView.widthAnchor.constraintEqualToConstant(collectionViewLayout.itemWidth)
|
let widthConstraint = self.prototypeCell.contentView.widthAnchor.constraint(equalToConstant: collectionViewLayout.itemWidth)
|
||||||
widthConstraint.active = true
|
widthConstraint.isActive = true
|
||||||
|
|
||||||
self.configureCell(self.prototypeCell, forIndexPath: indexPath)
|
self.configureCell(self.prototypeCell, forIndexPath: indexPath)
|
||||||
|
|
||||||
let size = self.prototypeCell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
|
let size = self.prototypeCell.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
|
||||||
|
|
||||||
widthConstraint.active = false
|
widthConstraint.isActive = false
|
||||||
|
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,44 +44,44 @@ class GridCollectionViewCell: UICollectionViewCell
|
|||||||
private func configureSubviews()
|
private func configureSubviews()
|
||||||
{
|
{
|
||||||
// Fix super annoying Unsatisfiable Constraints message in debugger by setting autoresizingMask
|
// Fix super annoying Unsatisfiable Constraints message in debugger by setting autoresizingMask
|
||||||
self.contentView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
|
self.contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||||
|
|
||||||
self.clipsToBounds = false
|
self.clipsToBounds = false
|
||||||
self.contentView.clipsToBounds = false
|
self.contentView.clipsToBounds = false
|
||||||
|
|
||||||
self.imageView.translatesAutoresizingMaskIntoConstraints = false
|
self.imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
self.imageView.contentMode = .ScaleAspectFit
|
self.imageView.contentMode = .scaleAspectFit
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
self.imageView.adjustsImageWhenAncestorFocused = true
|
self.imageView.adjustsImageWhenAncestorFocused = true
|
||||||
#endif
|
#endif
|
||||||
self.contentView.addSubview(self.imageView)
|
self.contentView.addSubview(self.imageView)
|
||||||
|
|
||||||
self.textLabel.translatesAutoresizingMaskIntoConstraints = false
|
self.textLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||||
self.textLabel.font = UIFont.boldSystemFontOfSize(12)
|
self.textLabel.font = UIFont.boldSystemFont(ofSize: 12)
|
||||||
self.textLabel.textAlignment = .Center
|
self.textLabel.textAlignment = .center
|
||||||
self.textLabel.numberOfLines = 0
|
self.textLabel.numberOfLines = 0
|
||||||
self.contentView.addSubview(self.textLabel)
|
self.contentView.addSubview(self.textLabel)
|
||||||
|
|
||||||
// Auto Layout
|
// Auto Layout
|
||||||
|
|
||||||
self.imageView.topAnchor.constraintEqualToAnchor(self.contentView.topAnchor).active = true
|
self.imageView.topAnchor.constraint(equalTo: self.contentView.topAnchor).isActive = true
|
||||||
self.imageView.centerXAnchor.constraintEqualToAnchor(self.contentView.centerXAnchor).active = true
|
self.imageView.centerXAnchor.constraint(equalTo: self.contentView.centerXAnchor).isActive = true
|
||||||
|
|
||||||
self.imageViewWidthConstraint = self.imageView.widthAnchor.constraintEqualToConstant(self.maximumImageSize.width)
|
self.imageViewWidthConstraint = self.imageView.widthAnchor.constraint(equalToConstant: self.maximumImageSize.width)
|
||||||
self.imageViewWidthConstraint.active = true
|
self.imageViewWidthConstraint.isActive = true
|
||||||
|
|
||||||
self.imageViewHeightConstraint = self.imageView.heightAnchor.constraintEqualToConstant(self.maximumImageSize.height)
|
self.imageViewHeightConstraint = self.imageView.heightAnchor.constraint(equalToConstant: self.maximumImageSize.height)
|
||||||
self.imageViewHeightConstraint.active = true
|
self.imageViewHeightConstraint.isActive = true
|
||||||
|
|
||||||
|
|
||||||
self.textLabel.trailingAnchor.constraintEqualToAnchor(self.contentView.trailingAnchor).active = true
|
self.textLabel.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor).isActive = true
|
||||||
self.textLabel.leadingAnchor.constraintEqualToAnchor(self.contentView.leadingAnchor).active = true
|
self.textLabel.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor).isActive = true
|
||||||
|
|
||||||
self.textLabelBottomAnchorConstraint = self.textLabel.bottomAnchor.constraintEqualToAnchor(self.contentView.bottomAnchor)
|
self.textLabelBottomAnchorConstraint = self.textLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor)
|
||||||
self.textLabelBottomAnchorConstraint.active = true
|
self.textLabelBottomAnchorConstraint.isActive = true
|
||||||
|
|
||||||
self.textLabelVerticalSpacingConstraint = self.textLabel.topAnchor.constraintEqualToAnchor(self.imageView.bottomAnchor)
|
self.textLabelVerticalSpacingConstraint = self.textLabel.topAnchor.constraint(equalTo: self.imageView.bottomAnchor)
|
||||||
self.textLabelVerticalSpacingConstraint.active = true
|
self.textLabelVerticalSpacingConstraint.isActive = true
|
||||||
|
|
||||||
|
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
@ -90,37 +90,37 @@ class GridCollectionViewCell: UICollectionViewCell
|
|||||||
self.textLabelFocusedVerticalSpacingConstraint = self.textLabel.topAnchor.constraintEqualToAnchor(self.imageView.focusedFrameGuide.bottomAnchor, constant: 0)
|
self.textLabelFocusedVerticalSpacingConstraint = self.textLabel.topAnchor.constraintEqualToAnchor(self.imageView.focusedFrameGuide.bottomAnchor, constant: 0)
|
||||||
self.textLabelFocusedVerticalSpacingConstraint?.active = true
|
self.textLabelFocusedVerticalSpacingConstraint?.active = true
|
||||||
#else
|
#else
|
||||||
self.textLabelVerticalSpacingConstraint.active = true
|
self.textLabelVerticalSpacingConstraint.isActive = true
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
self.updateMaximumImageSize()
|
self.updateMaximumImageSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator)
|
override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator)
|
||||||
{
|
{
|
||||||
super.didUpdateFocusInContext(context, withAnimationCoordinator: coordinator)
|
super.didUpdateFocus(in: context, with: coordinator)
|
||||||
|
|
||||||
coordinator.addCoordinatedAnimations({
|
coordinator.addCoordinatedAnimations({
|
||||||
|
|
||||||
if context.nextFocusedView == self
|
if context.nextFocusedView == self
|
||||||
{
|
{
|
||||||
self.textLabelBottomAnchorConstraint?.active = false
|
self.textLabelBottomAnchorConstraint?.isActive = false
|
||||||
self.textLabelVerticalSpacingConstraint.active = false
|
self.textLabelVerticalSpacingConstraint.isActive = false
|
||||||
|
|
||||||
self.textLabelFocusedVerticalSpacingConstraint?.active = true
|
self.textLabelFocusedVerticalSpacingConstraint?.isActive = true
|
||||||
|
|
||||||
self.textLabel.textColor = UIColor.whiteColor()
|
self.textLabel.textColor = UIColor.white()
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self.textLabelFocusedVerticalSpacingConstraint?.active = false
|
self.textLabelFocusedVerticalSpacingConstraint?.isActive = false
|
||||||
|
|
||||||
self.textLabelBottomAnchorConstraint?.active = true
|
self.textLabelBottomAnchorConstraint?.isActive = true
|
||||||
self.textLabelVerticalSpacingConstraint.active = true
|
self.textLabelVerticalSpacingConstraint.isActive = true
|
||||||
|
|
||||||
self.textLabel.textColor = UIColor.blackColor()
|
self.textLabel.textColor = UIColor.black()
|
||||||
}
|
}
|
||||||
|
|
||||||
self.layoutIfNeeded()
|
self.layoutIfNeeded()
|
||||||
|
|||||||
@ -29,7 +29,7 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]?
|
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?
|
||||||
{
|
{
|
||||||
guard let collectionView = self.collectionView else { return nil }
|
guard let collectionView = self.collectionView else { return nil }
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
|
|||||||
self.sectionInset.left = interitemSpacing
|
self.sectionInset.left = interitemSpacing
|
||||||
self.sectionInset.right = interitemSpacing
|
self.sectionInset.right = interitemSpacing
|
||||||
|
|
||||||
let layoutAttributes = super.layoutAttributesForElementsInRect(rect)?.map({ $0.copy() }) as! [UICollectionViewLayoutAttributes]
|
let layoutAttributes = super.layoutAttributesForElements(in: rect)?.map({ $0.copy() }) as! [UICollectionViewLayoutAttributes]
|
||||||
|
|
||||||
var minimumY: CGFloat? = nil
|
var minimumY: CGFloat? = nil
|
||||||
var maximumY: CGFloat? = nil
|
var maximumY: CGFloat? = nil
|
||||||
@ -47,9 +47,9 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
|
|||||||
|
|
||||||
var isSingleRow = true
|
var isSingleRow = true
|
||||||
|
|
||||||
for (index, attributes) in layoutAttributes.enumerate()
|
for (index, attributes) in layoutAttributes.enumerated()
|
||||||
{
|
{
|
||||||
guard attributes.representedElementCategory == .Cell else { continue }
|
guard attributes.representedElementCategory == .cell else { continue }
|
||||||
|
|
||||||
// Ensure equal spacing between items (that also match the section insets)
|
// Ensure equal spacing between items (that also match the section insets)
|
||||||
if index > 0
|
if index > 0
|
||||||
@ -103,7 +103,7 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
|
|||||||
{
|
{
|
||||||
let spacing = (collectionView.bounds.width - (self.itemWidth * CGFloat(tempLayoutAttributes.count))) / (CGFloat(tempLayoutAttributes.count) + 1.0)
|
let spacing = (collectionView.bounds.width - (self.itemWidth * CGFloat(tempLayoutAttributes.count))) / (CGFloat(tempLayoutAttributes.count) + 1.0)
|
||||||
|
|
||||||
for (index, layoutAttributes) in tempLayoutAttributes.enumerate()
|
for (index, layoutAttributes) in tempLayoutAttributes.enumerated()
|
||||||
{
|
{
|
||||||
layoutAttributes.frame.origin.x = spacing + (spacing + self.itemWidth) * CGFloat(index)
|
layoutAttributes.frame.origin.x = spacing + (spacing + self.itemWidth) * CGFloat(index)
|
||||||
}
|
}
|
||||||
@ -117,7 +117,7 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
|
|||||||
|
|
||||||
private extension GridCollectionViewLayout
|
private extension GridCollectionViewLayout
|
||||||
{
|
{
|
||||||
func alignLayoutAttributes(layoutAttributes: [UICollectionViewLayoutAttributes], toMinimumY minimumY: CGFloat)
|
func alignLayoutAttributes(_ layoutAttributes: [UICollectionViewLayoutAttributes], toMinimumY minimumY: CGFloat)
|
||||||
{
|
{
|
||||||
for attributes in layoutAttributes
|
for attributes in layoutAttributes
|
||||||
{
|
{
|
||||||
|
|||||||
@ -12,10 +12,10 @@ extension Action
|
|||||||
{
|
{
|
||||||
enum Style
|
enum Style
|
||||||
{
|
{
|
||||||
case Default
|
case `default`
|
||||||
case Cancel
|
case cancel
|
||||||
case Destructive
|
case destructive
|
||||||
case Selected
|
case selected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,9 +25,9 @@ extension Action.Style
|
|||||||
{
|
{
|
||||||
switch self
|
switch self
|
||||||
{
|
{
|
||||||
case .Default, .Selected: return .Default
|
case .default, .selected: return .default
|
||||||
case .Cancel: return .Cancel
|
case .cancel: return .cancel
|
||||||
case .Destructive: return .Destructive
|
case .destructive: return .destructive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,9 +35,9 @@ extension Action.Style
|
|||||||
{
|
{
|
||||||
switch self
|
switch self
|
||||||
{
|
{
|
||||||
case .Default, .Cancel: return .Default
|
case .default, .cancel: return .default
|
||||||
case .Destructive: return .Destructive
|
case .destructive: return .destructive
|
||||||
case .Selected: return .Selected
|
case .selected: return .selected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ struct Action
|
|||||||
{
|
{
|
||||||
let title: String
|
let title: String
|
||||||
let style: Style
|
let style: Style
|
||||||
let action: (Action -> Void)?
|
let action: ((Action) -> Void)?
|
||||||
|
|
||||||
var alertAction: UIAlertAction
|
var alertAction: UIAlertAction
|
||||||
{
|
{
|
||||||
|
|||||||
@ -50,6 +50,6 @@ class BoxArtImageView: UIImageView
|
|||||||
self.adjustsImageWhenAncestorFocused = true
|
self.adjustsImageWhenAncestorFocused = true
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
self.contentMode = .ScaleAspectFit
|
self.contentMode = .scaleAspectFit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,9 +13,9 @@ import Roxas
|
|||||||
|
|
||||||
public class LoadImageOperation: RSTOperation
|
public class LoadImageOperation: RSTOperation
|
||||||
{
|
{
|
||||||
public let URL: NSURL
|
public let URL: Foundation.URL
|
||||||
|
|
||||||
public var completionHandler: (UIImage? -> Void)? {
|
public var completionHandler: ((UIImage?) -> Void)? {
|
||||||
didSet {
|
didSet {
|
||||||
self.completionBlock = {
|
self.completionBlock = {
|
||||||
rst_dispatch_sync_on_main_thread() {
|
rst_dispatch_sync_on_main_thread() {
|
||||||
@ -25,16 +25,16 @@ public class LoadImageOperation: RSTOperation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public var imageCache: NSCache? {
|
public var imageCache: Cache<AnyObject, AnyObject>? {
|
||||||
didSet {
|
didSet {
|
||||||
// Ensures if an image is cached, it will be returned immediately, to prevent temporary flash of placeholder image
|
// Ensures if an image is cached, it will be returned immediately, to prevent temporary flash of placeholder image
|
||||||
self.immediate = self.imageCache?.objectForKey(self.URL) != nil
|
self.isImmediate = self.imageCache?.object(forKey: self.URL) != nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var image: UIImage?
|
private var image: UIImage?
|
||||||
|
|
||||||
public init(URL: NSURL)
|
public init(URL: Foundation.URL)
|
||||||
{
|
{
|
||||||
self.URL = URL
|
self.URL = URL
|
||||||
|
|
||||||
@ -46,9 +46,9 @@ public extension LoadImageOperation
|
|||||||
{
|
{
|
||||||
override func main()
|
override func main()
|
||||||
{
|
{
|
||||||
guard !self.cancelled else { return }
|
guard !self.isCancelled else { return }
|
||||||
|
|
||||||
if let cachedImage = self.imageCache?.objectForKey(self.URL) as? UIImage
|
if let cachedImage = self.imageCache?.object(forKey: self.URL) as? UIImage
|
||||||
{
|
{
|
||||||
self.image = cachedImage
|
self.image = cachedImage
|
||||||
return
|
return
|
||||||
@ -58,11 +58,11 @@ public extension LoadImageOperation
|
|||||||
|
|
||||||
if let imageSource = CGImageSourceCreateWithURL(self.URL, options), quartzImage = CGImageSourceCreateImageAtIndex(imageSource, 0, options)
|
if let imageSource = CGImageSourceCreateWithURL(self.URL, options), quartzImage = CGImageSourceCreateImageAtIndex(imageSource, 0, options)
|
||||||
{
|
{
|
||||||
let loadedImage = UIImage(CGImage: quartzImage)
|
let loadedImage = UIImage(cgImage: quartzImage)
|
||||||
|
|
||||||
// Force decompression of image
|
// Force decompression of image
|
||||||
UIGraphicsBeginImageContextWithOptions(CGSize(width: 1, height: 1), true, 1.0)
|
UIGraphicsBeginImageContextWithOptions(CGSize(width: 1, height: 1), true, 1.0)
|
||||||
loadedImage.drawAtPoint(CGPoint.zero)
|
loadedImage.draw(at: CGPoint.zero)
|
||||||
UIGraphicsEndImageContext()
|
UIGraphicsEndImageContext()
|
||||||
|
|
||||||
self.imageCache?.setObject(loadedImage, forKey: self.URL)
|
self.imageCache?.setObject(loadedImage, forKey: self.URL)
|
||||||
|
|||||||
@ -29,46 +29,46 @@ class DatabaseManager
|
|||||||
|
|
||||||
private init()
|
private init()
|
||||||
{
|
{
|
||||||
let modelURL = NSBundle.mainBundle().URLForResource("Model", withExtension: "momd")
|
let modelURL = Bundle.main.urlForResource("Model", withExtension: "momd")
|
||||||
let managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL!)
|
let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL!)
|
||||||
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel!)
|
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel!)
|
||||||
|
|
||||||
self.privateManagedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
|
self.privateManagedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
|
||||||
self.privateManagedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator
|
self.privateManagedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator
|
||||||
self.privateManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
self.privateManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
||||||
|
|
||||||
self.managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
|
self.managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
|
||||||
self.managedObjectContext.parentContext = self.privateManagedObjectContext
|
self.managedObjectContext.parent = self.privateManagedObjectContext
|
||||||
self.managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
self.managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
||||||
|
|
||||||
self.validationManagedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
|
self.validationManagedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
|
||||||
self.validationManagedObjectContext.parentContext = self.managedObjectContext
|
self.validationManagedObjectContext.parent = self.managedObjectContext
|
||||||
self.validationManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
self.validationManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
||||||
|
|
||||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(DatabaseManager.managedObjectContextWillSave(_:)), name: NSManagedObjectContextWillSaveNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(DatabaseManager.managedObjectContextWillSave(_:)), name: NSNotification.Name.NSManagedObjectContextWillSave, object: nil)
|
||||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(DatabaseManager.managedObjectContextDidSave(_:)), name: NSManagedObjectContextDidSaveNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(DatabaseManager.managedObjectContextDidSave(_:)), name: NSNotification.Name.NSManagedObjectContextDidSave, object: nil)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func startWithCompletion(completionBlock: ((performingMigration: Bool) -> Void)?)
|
func startWithCompletion(_ completionBlock: ((performingMigration: Bool) -> Void)?)
|
||||||
{
|
{
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
|
DispatchQueue.global(attributes: DispatchQueue.GlobalAttributes.qosUserInitiated).async {
|
||||||
|
|
||||||
let storeURL = DatabaseManager.databaseDirectoryURL.URLByAppendingPathComponent("Delta.sqlite")
|
let storeURL = try! DatabaseManager.databaseDirectoryURL.appendingPathComponent("Delta.sqlite")
|
||||||
|
|
||||||
let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
|
let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
|
||||||
|
|
||||||
var performingMigration = false
|
var performingMigration = false
|
||||||
|
|
||||||
if let sourceMetadata = try? NSPersistentStoreCoordinator.metadataForPersistentStoreOfType(NSSQLiteStoreType, URL: storeURL, options: options),
|
if let sourceMetadata = try? NSPersistentStoreCoordinator.metadataForPersistentStore(ofType: NSSQLiteStoreType, at: storeURL, options: options),
|
||||||
managedObjectModel = self.privateManagedObjectContext.persistentStoreCoordinator?.managedObjectModel
|
managedObjectModel = self.privateManagedObjectContext.persistentStoreCoordinator?.managedObjectModel
|
||||||
{
|
{
|
||||||
performingMigration = !managedObjectModel.isConfiguration(nil, compatibleWithStoreMetadata: sourceMetadata)
|
performingMigration = !managedObjectModel.isConfiguration(withName: nil, compatibleWithStoreMetadata: sourceMetadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
try self.privateManagedObjectContext.persistentStoreCoordinator?.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: options)
|
try self.privateManagedObjectContext.persistentStoreCoordinator?.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: options)
|
||||||
}
|
}
|
||||||
catch let error as NSError
|
catch let error as NSError
|
||||||
{
|
{
|
||||||
@ -94,16 +94,16 @@ class DatabaseManager
|
|||||||
// MARK: - Importing -
|
// MARK: - Importing -
|
||||||
/// Importing
|
/// Importing
|
||||||
|
|
||||||
func importGamesAtURLs(URLs: [NSURL], withCompletion completion: ([String] -> Void)?)
|
func importGamesAtURLs(_ URLs: [URL], withCompletion completion: (([String]) -> Void)?)
|
||||||
{
|
{
|
||||||
let managedObjectContext = self.backgroundManagedObjectContext()
|
let managedObjectContext = self.backgroundManagedObjectContext()
|
||||||
managedObjectContext.performBlock() {
|
managedObjectContext.perform() {
|
||||||
|
|
||||||
var identifiers: [String] = []
|
var identifiers: [String] = []
|
||||||
|
|
||||||
for URL in URLs
|
for URL in URLs
|
||||||
{
|
{
|
||||||
let identifier = FileHash.sha1HashOfFileAtPath(URL.path) as String
|
let identifier = FileHash.sha1HashOfFile(atPath: URL.path) as String
|
||||||
|
|
||||||
var filename = identifier
|
var filename = identifier
|
||||||
if let pathExtension = URL.pathExtension
|
if let pathExtension = URL.pathExtension
|
||||||
@ -112,7 +112,7 @@ class DatabaseManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
let game = Game.insertIntoManagedObjectContext(managedObjectContext)
|
let game = Game.insertIntoManagedObjectContext(managedObjectContext)
|
||||||
game.name = URL.URLByDeletingPathExtension?.lastPathComponent ?? NSLocalizedString("Game", comment: "")
|
game.name = try! URL.deletingPathExtension()?.lastPathComponent ?? NSLocalizedString("Game", comment: "")
|
||||||
game.identifier = identifier
|
game.identifier = identifier
|
||||||
game.filename = filename
|
game.filename = filename
|
||||||
|
|
||||||
@ -129,17 +129,17 @@ class DatabaseManager
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
let destinationURL = DatabaseManager.gamesDirectoryURL.URLByAppendingPathComponent(game.identifier + "." + game.preferredFileExtension)
|
let destinationURL = try! DatabaseManager.gamesDirectoryURL.appendingPathComponent(game.identifier + "." + game.preferredFileExtension)
|
||||||
|
|
||||||
if let path = destinationURL.path
|
if let path = destinationURL.path
|
||||||
{
|
{
|
||||||
if NSFileManager.defaultManager().fileExistsAtPath(path)
|
if FileManager.default.fileExists(atPath: path)
|
||||||
{
|
{
|
||||||
try NSFileManager.defaultManager().removeItemAtURL(URL)
|
try FileManager.default.removeItem(at: URL)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
try NSFileManager.defaultManager().moveItemAtURL(URL, toURL: destinationURL)
|
try FileManager.default.moveItem(at: URL, to: destinationURL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ class DatabaseManager
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
game.managedObjectContext?.deleteObject(game)
|
game.managedObjectContext?.delete(game)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -177,8 +177,8 @@ class DatabaseManager
|
|||||||
|
|
||||||
func backgroundManagedObjectContext() -> NSManagedObjectContext
|
func backgroundManagedObjectContext() -> NSManagedObjectContext
|
||||||
{
|
{
|
||||||
let managedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
|
let managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
|
||||||
managedObjectContext.parentContext = self.validationManagedObjectContext
|
managedObjectContext.parent = self.validationManagedObjectContext
|
||||||
managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
||||||
|
|
||||||
return managedObjectContext
|
return managedObjectContext
|
||||||
@ -187,44 +187,44 @@ class DatabaseManager
|
|||||||
|
|
||||||
extension DatabaseManager
|
extension DatabaseManager
|
||||||
{
|
{
|
||||||
class var databaseDirectoryURL: NSURL
|
class var databaseDirectoryURL: URL
|
||||||
{
|
{
|
||||||
let documentsDirectoryURL: NSURL
|
let documentsDirectoryURL: URL
|
||||||
|
|
||||||
if UIDevice.currentDevice().userInterfaceIdiom == .TV
|
if UIDevice.current().userInterfaceIdiom == .tv
|
||||||
{
|
{
|
||||||
documentsDirectoryURL = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.CachesDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).first!
|
documentsDirectoryURL = FileManager.default.urlsForDirectory(FileManager.SearchPathDirectory.cachesDirectory, inDomains: FileManager.SearchPathDomainMask.userDomainMask).first!
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
documentsDirectoryURL = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).first!
|
documentsDirectoryURL = FileManager.default.urlsForDirectory(FileManager.SearchPathDirectory.documentDirectory, inDomains: FileManager.SearchPathDomainMask.userDomainMask).first!
|
||||||
}
|
}
|
||||||
|
|
||||||
let databaseDirectoryURL = documentsDirectoryURL.URLByAppendingPathComponent("Database")
|
let databaseDirectoryURL = try! documentsDirectoryURL.appendingPathComponent("Database")
|
||||||
self.createDirectoryAtURLIfNeeded(databaseDirectoryURL)
|
self.createDirectoryAtURLIfNeeded(databaseDirectoryURL)
|
||||||
|
|
||||||
return databaseDirectoryURL
|
return databaseDirectoryURL
|
||||||
}
|
}
|
||||||
|
|
||||||
class var gamesDirectoryURL: NSURL
|
class var gamesDirectoryURL: URL
|
||||||
{
|
{
|
||||||
let gamesDirectoryURL = DatabaseManager.databaseDirectoryURL.URLByAppendingPathComponent("Games")
|
let gamesDirectoryURL = try! DatabaseManager.databaseDirectoryURL.appendingPathComponent("Games")
|
||||||
self.createDirectoryAtURLIfNeeded(gamesDirectoryURL)
|
self.createDirectoryAtURLIfNeeded(gamesDirectoryURL)
|
||||||
|
|
||||||
return gamesDirectoryURL
|
return gamesDirectoryURL
|
||||||
}
|
}
|
||||||
|
|
||||||
class var saveStatesDirectoryURL: NSURL
|
class var saveStatesDirectoryURL: URL
|
||||||
{
|
{
|
||||||
let saveStatesDirectoryURL = DatabaseManager.databaseDirectoryURL.URLByAppendingPathComponent("Save States")
|
let saveStatesDirectoryURL = try! DatabaseManager.databaseDirectoryURL.appendingPathComponent("Save States")
|
||||||
self.createDirectoryAtURLIfNeeded(saveStatesDirectoryURL)
|
self.createDirectoryAtURLIfNeeded(saveStatesDirectoryURL)
|
||||||
|
|
||||||
return saveStatesDirectoryURL
|
return saveStatesDirectoryURL
|
||||||
}
|
}
|
||||||
|
|
||||||
class func saveStatesDirectoryURLForGame(game: Game) -> NSURL
|
class func saveStatesDirectoryURLForGame(_ game: Game) -> URL
|
||||||
{
|
{
|
||||||
let gameDirectoryURL = DatabaseManager.saveStatesDirectoryURL.URLByAppendingPathComponent(game.identifier)
|
let gameDirectoryURL = try! DatabaseManager.saveStatesDirectoryURL.appendingPathComponent(game.identifier)
|
||||||
self.createDirectoryAtURLIfNeeded(gameDirectoryURL)
|
self.createDirectoryAtURLIfNeeded(gameDirectoryURL)
|
||||||
|
|
||||||
return gameDirectoryURL
|
return gameDirectoryURL
|
||||||
@ -239,7 +239,7 @@ private extension DatabaseManager
|
|||||||
{
|
{
|
||||||
let backgroundTaskIdentifier = RSTBeginBackgroundTask("Save Database Task")
|
let backgroundTaskIdentifier = RSTBeginBackgroundTask("Save Database Task")
|
||||||
|
|
||||||
self.validationManagedObjectContext.performBlockAndWait {
|
self.validationManagedObjectContext.performAndWait {
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -252,7 +252,7 @@ private extension DatabaseManager
|
|||||||
|
|
||||||
|
|
||||||
// Update main managed object context
|
// Update main managed object context
|
||||||
self.managedObjectContext.performBlockAndWait() {
|
self.managedObjectContext.performAndWait() {
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -265,7 +265,7 @@ private extension DatabaseManager
|
|||||||
|
|
||||||
|
|
||||||
// Save to disk
|
// Save to disk
|
||||||
self.privateManagedObjectContext.performBlock() {
|
self.privateManagedObjectContext.perform() {
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -287,22 +287,22 @@ private extension DatabaseManager
|
|||||||
|
|
||||||
// MARK: - Validation -
|
// MARK: - Validation -
|
||||||
|
|
||||||
func validateManagedObjectContextSave(managedObjectContext: NSManagedObjectContext)
|
func validateManagedObjectContextSave(_ managedObjectContext: NSManagedObjectContext)
|
||||||
{
|
{
|
||||||
// Remove deleted files from disk
|
// Remove deleted files from disk
|
||||||
for object in managedObjectContext.deletedObjects
|
for object in managedObjectContext.deletedObjects
|
||||||
{
|
{
|
||||||
var fileURLs = Set<NSURL>()
|
var fileURLs = Set<URL>()
|
||||||
|
|
||||||
let temporaryObject = self.validationManagedObjectContext.objectWithID(object.objectID)
|
let temporaryObject = self.validationManagedObjectContext.object(with: object.objectID)
|
||||||
switch temporaryObject
|
switch temporaryObject
|
||||||
{
|
{
|
||||||
case let game as Game:
|
case let game as Game:
|
||||||
fileURLs.insert(game.fileURL)
|
fileURLs.insert(game.fileURL as URL)
|
||||||
|
|
||||||
case let saveState as SaveState:
|
case let saveState as SaveState:
|
||||||
fileURLs.insert(saveState.fileURL)
|
fileURLs.insert(saveState.fileURL as URL)
|
||||||
fileURLs.insert(saveState.imageFileURL)
|
fileURLs.insert(saveState.imageFileURL as URL)
|
||||||
|
|
||||||
default: break
|
default: break
|
||||||
}
|
}
|
||||||
@ -311,7 +311,7 @@ private extension DatabaseManager
|
|||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
try NSFileManager.defaultManager().removeItemAtURL(URL)
|
try FileManager.default.removeItem(at: URL)
|
||||||
}
|
}
|
||||||
catch let error as NSError
|
catch let error as NSError
|
||||||
{
|
{
|
||||||
@ -321,39 +321,39 @@ private extension DatabaseManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove empty collections
|
// Remove empty collections
|
||||||
let collections = GameCollection.instancesWithPredicate(NSPredicate(format: "%K.@count == 0", GameCollection.Attributes.games.rawValue), inManagedObjectContext: self.validationManagedObjectContext, type: GameCollection.self)
|
let collections = GameCollection.instancesWithPredicate(Predicate(format: "%K.@count == 0", GameCollection.Attributes.games.rawValue), inManagedObjectContext: self.validationManagedObjectContext, type: GameCollection.self)
|
||||||
|
|
||||||
for collection in collections
|
for collection in collections
|
||||||
{
|
{
|
||||||
self.validationManagedObjectContext.deleteObject(collection)
|
self.validationManagedObjectContext.delete(collection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Notifications -
|
// MARK: - Notifications -
|
||||||
|
|
||||||
@objc func managedObjectContextWillSave(notification: NSNotification)
|
@objc func managedObjectContextWillSave(_ notification: Notification)
|
||||||
{
|
{
|
||||||
guard let managedObjectContext = notification.object as? NSManagedObjectContext where managedObjectContext.parentContext == self.validationManagedObjectContext else { return }
|
guard let managedObjectContext = notification.object as? NSManagedObjectContext where managedObjectContext.parent == self.validationManagedObjectContext else { return }
|
||||||
|
|
||||||
self.validationManagedObjectContext.performBlockAndWait {
|
self.validationManagedObjectContext.performAndWait {
|
||||||
self.validateManagedObjectContextSave(managedObjectContext)
|
self.validateManagedObjectContextSave(managedObjectContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func managedObjectContextDidSave(notification: NSNotification)
|
@objc func managedObjectContextDidSave(_ notification: Notification)
|
||||||
{
|
{
|
||||||
guard let managedObjectContext = notification.object as? NSManagedObjectContext where managedObjectContext.parentContext == self.validationManagedObjectContext else { return }
|
guard let managedObjectContext = notification.object as? NSManagedObjectContext where managedObjectContext.parent == self.validationManagedObjectContext else { return }
|
||||||
|
|
||||||
self.save()
|
self.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - File Management -
|
// MARK: - File Management -
|
||||||
|
|
||||||
class func createDirectoryAtURLIfNeeded(URL: NSURL)
|
class func createDirectoryAtURLIfNeeded(_ URL: Foundation.URL)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
try NSFileManager.defaultManager().createDirectoryAtURL(URL, withIntermediateDirectories: true, attributes: nil)
|
try FileManager.default.createDirectory(at: URL, withIntermediateDirectories: true, attributes: nil)
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|||||||
@ -59,11 +59,11 @@ class Cheat: NSManagedObject, CheatProtocol
|
|||||||
//TODO: Change type to String! when Swift 3 allows it
|
//TODO: Change type to String! when Swift 3 allows it
|
||||||
@NSManaged var name: String?
|
@NSManaged var name: String?
|
||||||
@NSManaged var code: String
|
@NSManaged var code: String
|
||||||
@NSManaged var modifiedDate: NSDate
|
@NSManaged var modifiedDate: Date
|
||||||
@NSManaged var enabled: Bool
|
@NSManaged var enabled: Bool
|
||||||
|
|
||||||
@NSManaged private(set) var identifier: String
|
@NSManaged private(set) var identifier: String
|
||||||
@NSManaged private(set) var creationDate: NSDate
|
@NSManaged private(set) var creationDate: Date
|
||||||
|
|
||||||
// Must be optional relationship to satisfy weird Core Data requirement
|
// Must be optional relationship to satisfy weird Core Data requirement
|
||||||
// https://forums.developer.apple.com/thread/20535
|
// https://forums.developer.apple.com/thread/20535
|
||||||
@ -73,16 +73,16 @@ class Cheat: NSManagedObject, CheatProtocol
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
self.willAccessValueForKey(Attributes.type.rawValue)
|
self.willAccessValue(forKey: Attributes.type.rawValue)
|
||||||
let type = CheatType(rawValue: self.primitiveType.shortValue)!
|
let type = CheatType(rawValue: self.primitiveType.int16Value)!
|
||||||
self.didAccessValueForKey(Attributes.type.rawValue)
|
self.didAccessValue(forKey: Attributes.type.rawValue)
|
||||||
return type
|
return type
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
self.willChangeValueForKey(Attributes.type.rawValue)
|
self.willChangeValue(forKey: Attributes.type.rawValue)
|
||||||
self.primitiveType = NSNumber(short: newValue.rawValue)
|
self.primitiveType = NSNumber(value: newValue.rawValue)
|
||||||
self.didChangeValueForKey(Attributes.type.rawValue)
|
self.didChangeValue(forKey: Attributes.type.rawValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,16 +90,16 @@ class Cheat: NSManagedObject, CheatProtocol
|
|||||||
extension Cheat
|
extension Cheat
|
||||||
{
|
{
|
||||||
@NSManaged private var primitiveIdentifier: String
|
@NSManaged private var primitiveIdentifier: String
|
||||||
@NSManaged private var primitiveCreationDate: NSDate
|
@NSManaged private var primitiveCreationDate: Date
|
||||||
@NSManaged private var primitiveModifiedDate: NSDate
|
@NSManaged private var primitiveModifiedDate: Date
|
||||||
@NSManaged private var primitiveType: NSNumber
|
@NSManaged private var primitiveType: NSNumber
|
||||||
|
|
||||||
override func awakeFromInsert()
|
override func awakeFromInsert()
|
||||||
{
|
{
|
||||||
super.awakeFromInsert()
|
super.awakeFromInsert()
|
||||||
|
|
||||||
let identifier = NSUUID().UUIDString
|
let identifier = UUID().uuidString
|
||||||
let date = NSDate()
|
let date = Date()
|
||||||
|
|
||||||
self.primitiveIdentifier = identifier
|
self.primitiveIdentifier = identifier
|
||||||
self.primitiveCreationDate = date
|
self.primitiveCreationDate = date
|
||||||
|
|||||||
@ -33,7 +33,7 @@ extension Game
|
|||||||
@objc(Game)
|
@objc(Game)
|
||||||
class Game: NSManagedObject, GameType
|
class Game: NSManagedObject, GameType
|
||||||
{
|
{
|
||||||
@NSManaged var artworkURL: NSURL?
|
@NSManaged var artworkURL: URL?
|
||||||
@NSManaged var filename: String
|
@NSManaged var filename: String
|
||||||
@NSManaged var identifier: String
|
@NSManaged var identifier: String
|
||||||
@NSManaged var name: String
|
@NSManaged var name: String
|
||||||
@ -42,9 +42,9 @@ class Game: NSManagedObject, GameType
|
|||||||
@NSManaged var gameCollections: Set<GameCollection>
|
@NSManaged var gameCollections: Set<GameCollection>
|
||||||
@NSManaged var previewSaveState: SaveState?
|
@NSManaged var previewSaveState: SaveState?
|
||||||
|
|
||||||
var fileURL: NSURL {
|
var fileURL: URL {
|
||||||
let fileURL = DatabaseManager.gamesDirectoryURL.URLByAppendingPathComponent(self.filename)
|
let fileURL = try! DatabaseManager.gamesDirectoryURL.appendingPathComponent(self.filename)
|
||||||
return fileURL
|
return fileURL!
|
||||||
}
|
}
|
||||||
|
|
||||||
var preferredFileExtension: String {
|
var preferredFileExtension: String {
|
||||||
|
|||||||
@ -54,7 +54,7 @@ class GameCollection: NSManagedObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class func gameSystemCollectionForPathExtension(pathExtension: String?, inManagedObjectContext managedObjectContext: NSManagedObjectContext) -> GameCollection
|
class func gameSystemCollectionForPathExtension(_ pathExtension: String?, inManagedObjectContext managedObjectContext: NSManagedObjectContext) -> GameCollection
|
||||||
{
|
{
|
||||||
let identifier: String
|
let identifier: String
|
||||||
let index: Int16
|
let index: Int16
|
||||||
@ -76,7 +76,7 @@ class GameCollection: NSManagedObject
|
|||||||
index = Int16(INT16_MAX)
|
index = Int16(INT16_MAX)
|
||||||
}
|
}
|
||||||
|
|
||||||
let predicate = NSPredicate(format: "%K == %@", GameCollection.Attributes.identifier.rawValue, identifier)
|
let predicate = Predicate(format: "%K == %@", GameCollection.Attributes.identifier.rawValue, identifier)
|
||||||
|
|
||||||
var gameCollection = GameCollection.instancesWithPredicate(predicate, inManagedObjectContext: managedObjectContext, type: GameCollection.self).first
|
var gameCollection = GameCollection.instancesWithPredicate(predicate, inManagedObjectContext: managedObjectContext, type: GameCollection.self).first
|
||||||
if gameCollection == nil
|
if gameCollection == nil
|
||||||
|
|||||||
@ -28,9 +28,9 @@ extension SaveState
|
|||||||
|
|
||||||
@objc enum Type: Int16
|
@objc enum Type: Int16
|
||||||
{
|
{
|
||||||
case Auto
|
case auto
|
||||||
case General
|
case general
|
||||||
case Locked
|
case locked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,12 +38,12 @@ extension SaveState
|
|||||||
class SaveState: NSManagedObject, SaveStateType
|
class SaveState: NSManagedObject, SaveStateType
|
||||||
{
|
{
|
||||||
@NSManaged var name: String?
|
@NSManaged var name: String?
|
||||||
@NSManaged var modifiedDate: NSDate
|
@NSManaged var modifiedDate: Date
|
||||||
@NSManaged var type: Type
|
@NSManaged var type: Type
|
||||||
|
|
||||||
@NSManaged private(set) var filename: String
|
@NSManaged private(set) var filename: String
|
||||||
@NSManaged private(set) var identifier: String
|
@NSManaged private(set) var identifier: String
|
||||||
@NSManaged private(set) var creationDate: NSDate
|
@NSManaged private(set) var creationDate: Date
|
||||||
|
|
||||||
// Must be optional relationship to satisfy weird Core Data requirement
|
// Must be optional relationship to satisfy weird Core Data requirement
|
||||||
// https://forums.developer.apple.com/thread/20535
|
// https://forums.developer.apple.com/thread/20535
|
||||||
@ -51,14 +51,14 @@ class SaveState: NSManagedObject, SaveStateType
|
|||||||
|
|
||||||
@NSManaged var previewGame: Game?
|
@NSManaged var previewGame: Game?
|
||||||
|
|
||||||
var fileURL: NSURL {
|
var fileURL: URL {
|
||||||
let fileURL = DatabaseManager.saveStatesDirectoryURLForGame(self.game).URLByAppendingPathComponent(self.filename)
|
let fileURL = try! DatabaseManager.saveStatesDirectoryURLForGame(self.game).appendingPathComponent(self.filename)
|
||||||
return fileURL
|
return fileURL
|
||||||
}
|
}
|
||||||
|
|
||||||
var imageFileURL: NSURL {
|
var imageFileURL: URL {
|
||||||
let imageFilename = (self.filename as NSString).stringByDeletingPathExtension + ".png"
|
let imageFilename = (self.filename as NSString).deletingPathExtension + ".png"
|
||||||
let imageFileURL = DatabaseManager.saveStatesDirectoryURLForGame(self.game).URLByAppendingPathComponent(imageFilename)
|
let imageFileURL = try! DatabaseManager.saveStatesDirectoryURLForGame(self.game).appendingPathComponent(imageFilename)
|
||||||
return imageFileURL
|
return imageFileURL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,15 +67,15 @@ extension SaveState
|
|||||||
{
|
{
|
||||||
@NSManaged private var primitiveFilename: String
|
@NSManaged private var primitiveFilename: String
|
||||||
@NSManaged private var primitiveIdentifier: String
|
@NSManaged private var primitiveIdentifier: String
|
||||||
@NSManaged private var primitiveCreationDate: NSDate
|
@NSManaged private var primitiveCreationDate: Date
|
||||||
@NSManaged private var primitiveModifiedDate: NSDate
|
@NSManaged private var primitiveModifiedDate: Date
|
||||||
|
|
||||||
override func awakeFromInsert()
|
override func awakeFromInsert()
|
||||||
{
|
{
|
||||||
super.awakeFromInsert()
|
super.awakeFromInsert()
|
||||||
|
|
||||||
let identifier = NSUUID().UUIDString
|
let identifier = UUID().uuidString
|
||||||
let date = NSDate()
|
let date = Date()
|
||||||
|
|
||||||
self.primitiveIdentifier = identifier
|
self.primitiveIdentifier = identifier
|
||||||
self.primitiveFilename = identifier
|
self.primitiveFilename = identifier
|
||||||
|
|||||||
@ -15,31 +15,31 @@ extension NSManagedObject
|
|||||||
return NSStringFromClass(self)
|
return NSStringFromClass(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
class func insertIntoManagedObjectContext(managedObjectContext: NSManagedObjectContext) -> Self
|
class func insertIntoManagedObjectContext(_ managedObjectContext: NSManagedObjectContext) -> Self
|
||||||
{
|
{
|
||||||
return self.insertIntoManagedObjectContext(managedObjectContext, type: self)
|
return self.insertIntoManagedObjectContext(managedObjectContext, type: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class func insertIntoManagedObjectContext<T>(managedObjectContext: NSManagedObjectContext, type: T.Type) -> T
|
private class func insertIntoManagedObjectContext<T>(_ managedObjectContext: NSManagedObjectContext, type: T.Type) -> T
|
||||||
{
|
{
|
||||||
let object = NSEntityDescription.insertNewObjectForEntityForName(self.entityName, inManagedObjectContext: managedObjectContext) as! T
|
let object = NSEntityDescription.insertNewObject(forEntityName: self.entityName, into: managedObjectContext) as! T
|
||||||
return object
|
return object
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Fetches -
|
// MARK: - Fetches -
|
||||||
|
|
||||||
class func fetchRequest() -> NSFetchRequest
|
class func fetchRequest() -> NSFetchRequest<AnyObject>
|
||||||
{
|
{
|
||||||
let fetchRequest = NSFetchRequest(entityName: self.entityName)
|
let fetchRequest = NSFetchRequest(entityName: self.entityName)
|
||||||
return fetchRequest
|
return fetchRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
class func instancesInManagedObjectContext<T: NSManagedObject>(managedObjectContext: NSManagedObjectContext, type: T.Type) -> [T]
|
class func instancesInManagedObjectContext<T: NSManagedObject>(_ managedObjectContext: NSManagedObjectContext, type: T.Type) -> [T]
|
||||||
{
|
{
|
||||||
return self.instancesWithPredicate(nil, inManagedObjectContext: managedObjectContext, type: type)
|
return self.instancesWithPredicate(nil, inManagedObjectContext: managedObjectContext, type: type)
|
||||||
}
|
}
|
||||||
|
|
||||||
class func instancesWithPredicate<T: NSManagedObject>(predicate: NSPredicate?, inManagedObjectContext managedObjectContext: NSManagedObjectContext, type: T.Type) -> [T]
|
class func instancesWithPredicate<T: NSManagedObject>(_ predicate: Predicate?, inManagedObjectContext managedObjectContext: NSManagedObjectContext, type: T.Type) -> [T]
|
||||||
{
|
{
|
||||||
let fetchRequest = self.fetchRequest()
|
let fetchRequest = self.fetchRequest()
|
||||||
fetchRequest.predicate = predicate
|
fetchRequest.predicate = predicate
|
||||||
@ -48,7 +48,7 @@ extension NSManagedObject
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
results = try managedObjectContext.executeFetchRequest(fetchRequest) as! [T]
|
results = try managedObjectContext.fetch(fetchRequest) as! [T]
|
||||||
}
|
}
|
||||||
catch let error as NSError
|
catch let error as NSError
|
||||||
{
|
{
|
||||||
|
|||||||
@ -13,15 +13,15 @@ import DeltaCore
|
|||||||
|
|
||||||
protocol GamePickerControllerDelegate
|
protocol GamePickerControllerDelegate
|
||||||
{
|
{
|
||||||
func gamePickerController(gamePickerController: GamePickerController, didImportGames games: [Game])
|
func gamePickerController(_ gamePickerController: GamePickerController, didImportGames games: [Game])
|
||||||
|
|
||||||
/** Optional **/
|
/** Optional **/
|
||||||
func gamePickerControllerDidCancel(gamePickerController: GamePickerController)
|
func gamePickerControllerDidCancel(_ gamePickerController: GamePickerController)
|
||||||
}
|
}
|
||||||
|
|
||||||
extension GamePickerControllerDelegate
|
extension GamePickerControllerDelegate
|
||||||
{
|
{
|
||||||
func gamePickerControllerDidCancel(gamePickerController: GamePickerController)
|
func gamePickerControllerDidCancel(_ gamePickerController: GamePickerController)
|
||||||
{
|
{
|
||||||
// Empty Implementation
|
// Empty Implementation
|
||||||
}
|
}
|
||||||
@ -33,34 +33,34 @@ class GamePickerController: NSObject
|
|||||||
|
|
||||||
private weak var presentingViewController: UIViewController?
|
private weak var presentingViewController: UIViewController?
|
||||||
|
|
||||||
private func presentGamePickerControllerFromPresentingViewController(presentingViewController: UIViewController, animated: Bool, completion: (Void -> Void)?)
|
private func presentGamePickerControllerFromPresentingViewController(_ presentingViewController: UIViewController, animated: Bool, completion: ((Void) -> Void)?)
|
||||||
{
|
{
|
||||||
self.presentingViewController = presentingViewController
|
self.presentingViewController = presentingViewController
|
||||||
|
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
let documentMenuController = UIDocumentMenuViewController(documentTypes: Array(Game.supportedTypeIdentifiers()), inMode: .Import)
|
let documentMenuController = UIDocumentMenuViewController(documentTypes: Array(Game.supportedTypeIdentifiers()), in: .import)
|
||||||
documentMenuController.delegate = self
|
documentMenuController.delegate = self
|
||||||
documentMenuController.addOptionWithTitle(NSLocalizedString("iTunes", comment: ""), image: nil, order: .First) { self.importFromiTunes(nil) }
|
documentMenuController.addOption(withTitle: NSLocalizedString("iTunes", comment: ""), image: nil, order: .first) { self.importFromiTunes(nil) }
|
||||||
self.presentingViewController?.presentViewController(documentMenuController, animated: true, completion: nil)
|
self.presentingViewController?.present(documentMenuController, animated: true, completion: nil)
|
||||||
#else
|
#else
|
||||||
self.importFromiTunes(completion)
|
self.importFromiTunes(completion)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private func importFromiTunes(completion: (Void -> Void)?)
|
private func importFromiTunes(_ completion: ((Void) -> Void)?)
|
||||||
{
|
{
|
||||||
let alertController = UIAlertController(title: NSLocalizedString("Import from iTunes?", comment: ""), message: NSLocalizedString("Delta will import the games copied over via iTunes.", comment: ""), preferredStyle: .Alert)
|
let alertController = UIAlertController(title: NSLocalizedString("Import from iTunes?", comment: ""), message: NSLocalizedString("Delta will import the games copied over via iTunes.", comment: ""), preferredStyle: .alert)
|
||||||
|
|
||||||
let importAction = UIAlertAction(title: NSLocalizedString("Import", comment: ""), style: .Default) { action in
|
let importAction = UIAlertAction(title: NSLocalizedString("Import", comment: ""), style: .default) { action in
|
||||||
|
|
||||||
let documentsDirectoryURL = DatabaseManager.databaseDirectoryURL.URLByDeletingLastPathComponent
|
let documentsDirectoryURL = try! DatabaseManager.databaseDirectoryURL.deletingLastPathComponent
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
let contents = try NSFileManager.defaultManager().contentsOfDirectoryAtURL(documentsDirectoryURL!, includingPropertiesForKeys: nil, options: .SkipsHiddenFiles)
|
let contents = try FileManager.default.contentsOfDirectory(at: documentsDirectoryURL!, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
|
||||||
|
|
||||||
let managedObjectContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let managedObjectContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
managedObjectContext.performBlock() {
|
managedObjectContext.perform() {
|
||||||
let gameURLs = contents.filter({ GameCollection.gameSystemCollectionForPathExtension($0.pathExtension, inManagedObjectContext: managedObjectContext).identifier != kUTTypeDeltaGame as String })
|
let gameURLs = contents.filter({ GameCollection.gameSystemCollectionForPathExtension($0.pathExtension, inManagedObjectContext: managedObjectContext).identifier != kUTTypeDeltaGame as String })
|
||||||
self.importGamesAtURLs(gameURLs)
|
self.importGamesAtURLs(gameURLs)
|
||||||
}
|
}
|
||||||
@ -76,22 +76,22 @@ class GamePickerController: NSObject
|
|||||||
}
|
}
|
||||||
alertController.addAction(importAction)
|
alertController.addAction(importAction)
|
||||||
|
|
||||||
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel) { action in
|
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel) { action in
|
||||||
self.delegate?.gamePickerControllerDidCancel(self)
|
self.delegate?.gamePickerControllerDidCancel(self)
|
||||||
self.presentingViewController?.gamePickerController = nil
|
self.presentingViewController?.gamePickerController = nil
|
||||||
}
|
}
|
||||||
alertController.addAction(cancelAction)
|
alertController.addAction(cancelAction)
|
||||||
|
|
||||||
self.presentingViewController?.presentViewController(alertController, animated: true, completion: completion)
|
self.presentingViewController?.present(alertController, animated: true, completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func importGamesAtURLs(URLs: [NSURL])
|
private func importGamesAtURLs(_ URLs: [URL])
|
||||||
{
|
{
|
||||||
DatabaseManager.sharedManager.importGamesAtURLs(URLs) { identifiers in
|
DatabaseManager.sharedManager.importGamesAtURLs(URLs) { identifiers in
|
||||||
|
|
||||||
DatabaseManager.sharedManager.managedObjectContext.performBlock() {
|
DatabaseManager.sharedManager.managedObjectContext.perform() {
|
||||||
|
|
||||||
let predicate = NSPredicate(format: "%K IN (%@)", Game.Attributes.identifier.rawValue, identifiers)
|
let predicate = Predicate(format: "%K IN (%@)", Game.Attributes.identifier.rawValue, identifiers)
|
||||||
let games = Game.instancesWithPredicate(predicate, inManagedObjectContext: DatabaseManager.sharedManager.managedObjectContext, type: Game.self)
|
let games = Game.instancesWithPredicate(predicate, inManagedObjectContext: DatabaseManager.sharedManager.managedObjectContext, type: Game.self)
|
||||||
|
|
||||||
self.delegate?.gamePickerController(self, didImportGames: games)
|
self.delegate?.gamePickerController(self, didImportGames: games)
|
||||||
@ -107,15 +107,15 @@ class GamePickerController: NSObject
|
|||||||
|
|
||||||
extension GamePickerController: UIDocumentMenuDelegate
|
extension GamePickerController: UIDocumentMenuDelegate
|
||||||
{
|
{
|
||||||
func documentMenu(documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController)
|
func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController)
|
||||||
{
|
{
|
||||||
documentPicker.delegate = self
|
documentPicker.delegate = self
|
||||||
self.presentingViewController?.presentViewController(documentPicker, animated: true, completion: nil)
|
self.presentingViewController?.present(documentPicker, animated: true, completion: nil)
|
||||||
|
|
||||||
self.presentingViewController?.gamePickerController = nil
|
self.presentingViewController?.gamePickerController = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentMenuWasCancelled(documentMenu: UIDocumentMenuViewController)
|
func documentMenuWasCancelled(_ documentMenu: UIDocumentMenuViewController)
|
||||||
{
|
{
|
||||||
self.delegate?.gamePickerControllerDidCancel(self)
|
self.delegate?.gamePickerControllerDidCancel(self)
|
||||||
|
|
||||||
@ -126,14 +126,14 @@ class GamePickerController: NSObject
|
|||||||
|
|
||||||
extension GamePickerController: UIDocumentPickerDelegate
|
extension GamePickerController: UIDocumentPickerDelegate
|
||||||
{
|
{
|
||||||
func documentPicker(controller: UIDocumentPickerViewController, didPickDocumentAtURL url: NSURL)
|
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL)
|
||||||
{
|
{
|
||||||
self.importGamesAtURLs([url])
|
self.importGamesAtURLs([url])
|
||||||
|
|
||||||
self.presentingViewController?.gamePickerController = nil
|
self.presentingViewController?.gamePickerController = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentPickerWasCancelled(controller: UIDocumentPickerViewController)
|
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController)
|
||||||
{
|
{
|
||||||
self.delegate?.gamePickerControllerDidCancel(self)
|
self.delegate?.gamePickerControllerDidCancel(self)
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ extension UIViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func presentGamePickerController(gamePickerController: GamePickerController, animated: Bool, completion: (Void -> Void)?)
|
func presentGamePickerController(_ gamePickerController: GamePickerController, animated: Bool, completion: ((Void) -> Void)?)
|
||||||
{
|
{
|
||||||
self.gamePickerController = gamePickerController
|
self.gamePickerController = gamePickerController
|
||||||
|
|
||||||
|
|||||||
@ -439,6 +439,7 @@
|
|||||||
BFFA71D61AAC406100EE9DD1 = {
|
BFFA71D61AAC406100EE9DD1 = {
|
||||||
CreatedOnToolsVersion = 6.3;
|
CreatedOnToolsVersion = 6.3;
|
||||||
DevelopmentTeam = 6XVY5G3U44;
|
DevelopmentTeam = 6XVY5G3U44;
|
||||||
|
LastSwiftMigration = 0800;
|
||||||
SystemCapabilities = {
|
SystemCapabilities = {
|
||||||
com.apple.iCloud = {
|
com.apple.iCloud = {
|
||||||
enabled = 1;
|
enabled = 1;
|
||||||
@ -706,6 +707,7 @@
|
|||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Delta/Supporting Files/Delta-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Delta/Supporting Files/Delta-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@ -720,6 +722,7 @@
|
|||||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Delta/Supporting Files/Delta-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Delta/Supporting Files/Delta-Bridging-Header.h";
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -15,19 +15,19 @@ class AppDelegate: UIResponder, UIApplicationDelegate
|
|||||||
{
|
{
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
|
|
||||||
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
|
||||||
{
|
{
|
||||||
self.window?.tintColor = UIColor.deltaPurpleColor()
|
self.window?.tintColor = UIColor.deltaPurpleColor()
|
||||||
|
|
||||||
// Database
|
// Database
|
||||||
|
|
||||||
let semaphore = dispatch_semaphore_create(0)
|
let semaphore = DispatchSemaphore(value: 0)
|
||||||
|
|
||||||
DatabaseManager.sharedManager.startWithCompletion { performingMigration in
|
DatabaseManager.sharedManager.startWithCompletion { performingMigration in
|
||||||
dispatch_semaphore_signal(semaphore)
|
semaphore.signal()
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
|
semaphore.wait(timeout: DispatchTime.distantFuture)
|
||||||
|
|
||||||
// Controllers
|
// Controllers
|
||||||
ExternalControllerManager.sharedManager.startMonitoringExternalControllers()
|
ExternalControllerManager.sharedManager.startMonitoringExternalControllers()
|
||||||
@ -35,29 +35,29 @@ class AppDelegate: UIResponder, UIApplicationDelegate
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationWillResignActive(application: UIApplication)
|
func applicationWillResignActive(_ application: UIApplication)
|
||||||
{
|
{
|
||||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationDidEnterBackground(application: UIApplication)
|
func applicationDidEnterBackground(_ application: UIApplication)
|
||||||
{
|
{
|
||||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationWillEnterForeground(application: UIApplication)
|
func applicationWillEnterForeground(_ application: UIApplication)
|
||||||
{
|
{
|
||||||
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationDidBecomeActive(application: UIApplication)
|
func applicationDidBecomeActive(_ application: UIApplication)
|
||||||
{
|
{
|
||||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationWillTerminate(application: UIApplication)
|
func applicationWillTerminate(_ application: UIApplication)
|
||||||
{
|
{
|
||||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import Roxas
|
|||||||
// Temporary wrapper around dispatch_semaphore_t until Swift 3 + modernized libdispatch
|
// Temporary wrapper around dispatch_semaphore_t until Swift 3 + modernized libdispatch
|
||||||
private struct DispatchSemaphore: Hashable
|
private struct DispatchSemaphore: Hashable
|
||||||
{
|
{
|
||||||
let semaphore: dispatch_semaphore_t
|
let semaphore: Dispatch.DispatchSemaphore
|
||||||
|
|
||||||
var hashValue: Int {
|
var hashValue: Int {
|
||||||
return semaphore.hash
|
return semaphore.hash
|
||||||
@ -22,7 +22,7 @@ private struct DispatchSemaphore: Hashable
|
|||||||
|
|
||||||
init(value: Int)
|
init(value: Int)
|
||||||
{
|
{
|
||||||
self.semaphore = dispatch_semaphore_create(value)
|
self.semaphore = DispatchSemaphore(value: value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ class EmulationViewController: UIViewController
|
|||||||
// Annoying iOS gotcha: if the previewingContext(_:viewControllerForLocation:) callback takes too long, the peek/preview starts, but fails to actually present the view controller
|
// Annoying iOS gotcha: if the previewingContext(_:viewControllerForLocation:) callback takes too long, the peek/preview starts, but fails to actually present the view controller
|
||||||
// To workaround, we have this closure to defer work for Peeking/Popping until the view controller appears
|
// To workaround, we have this closure to defer work for Peeking/Popping until the view controller appears
|
||||||
// Hacky, but works
|
// Hacky, but works
|
||||||
var deferredPreparationHandler: (Void -> Void)?
|
var deferredPreparationHandler: ((Void) -> Void)?
|
||||||
|
|
||||||
//MARK: - Private Properties
|
//MARK: - Private Properties
|
||||||
private var pauseViewController: PauseViewController?
|
private var pauseViewController: PauseViewController?
|
||||||
@ -77,7 +77,7 @@ class EmulationViewController: UIViewController
|
|||||||
private var updateSemaphores = Set<DispatchSemaphore>()
|
private var updateSemaphores = Set<DispatchSemaphore>()
|
||||||
|
|
||||||
private var sustainedInputs = [ObjectIdentifier: [InputType]]()
|
private var sustainedInputs = [ObjectIdentifier: [InputType]]()
|
||||||
private var reactivateSustainInputsQueue: NSOperationQueue
|
private var reactivateSustainInputsQueue: OperationQueue
|
||||||
private var choosingSustainedButtons = false
|
private var choosingSustainedButtons = false
|
||||||
|
|
||||||
@IBOutlet private var controllerView: ControllerView!
|
@IBOutlet private var controllerView: ControllerView!
|
||||||
@ -92,16 +92,16 @@ class EmulationViewController: UIViewController
|
|||||||
/** Initializers **/
|
/** Initializers **/
|
||||||
required init?(coder aDecoder: NSCoder)
|
required init?(coder aDecoder: NSCoder)
|
||||||
{
|
{
|
||||||
self.reactivateSustainInputsQueue = NSOperationQueue()
|
self.reactivateSustainInputsQueue = OperationQueue()
|
||||||
self.reactivateSustainInputsQueue.maxConcurrentOperationCount = 1
|
self.reactivateSustainInputsQueue.maxConcurrentOperationCount = 1
|
||||||
|
|
||||||
super.init(coder: aDecoder)
|
super.init(coder: aDecoder)
|
||||||
|
|
||||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(EmulationViewController.updateControllers), name: ExternalControllerDidConnectNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(EmulationViewController.updateControllers), name: ExternalControllerDidConnectNotification, object: nil)
|
||||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(EmulationViewController.updateControllers), name: ExternalControllerDidDisconnectNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(EmulationViewController.updateControllers), name: ExternalControllerDidDisconnectNotification, object: nil)
|
||||||
|
|
||||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(EmulationViewController.willResignActive(_:)), name: UIApplicationWillResignActiveNotification, object: UIApplication.sharedApplication())
|
NotificationCenter.default.addObserver(self, selector: #selector(EmulationViewController.willResignActive(_:)), name: NSNotification.Name.UIApplicationWillResignActive, object: UIApplication.shared())
|
||||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(EmulationViewController.didBecomeActive(_:)), name: UIApplicationDidBecomeActiveNotification, object: UIApplication.sharedApplication())
|
NotificationCenter.default.addObserver(self, selector: #selector(EmulationViewController.didBecomeActive(_:)), name: NSNotification.Name.UIApplicationDidBecomeActive, object: UIApplication.shared())
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit
|
deinit
|
||||||
@ -123,7 +123,7 @@ class EmulationViewController: UIViewController
|
|||||||
// (such as when peeking and popping)
|
// (such as when peeking and popping)
|
||||||
self.controllerViewHeightConstraint.constant = 0
|
self.controllerViewHeightConstraint.constant = 0
|
||||||
|
|
||||||
self.gameView.backgroundColor = UIColor.clearColor()
|
self.gameView.backgroundColor = UIColor.clear()
|
||||||
self.emulatorCore.addGameView(self.gameView)
|
self.emulatorCore.addGameView(self.gameView)
|
||||||
|
|
||||||
self.backgroundView.textLabel.text = NSLocalizedString("Select Buttons to Sustain", comment: "")
|
self.backgroundView.textLabel.text = NSLocalizedString("Select Buttons to Sustain", comment: "")
|
||||||
@ -137,7 +137,7 @@ class EmulationViewController: UIViewController
|
|||||||
self.updateControllers()
|
self.updateControllers()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidAppear(animated: Bool)
|
override func viewDidAppear(_ animated: Bool)
|
||||||
{
|
{
|
||||||
super.viewDidAppear(animated)
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
@ -147,12 +147,12 @@ class EmulationViewController: UIViewController
|
|||||||
// Yes, order DOES matter here, in order to prevent audio from being slightly delayed after peeking with 3D Touch (ugh so tired of that issue)
|
// Yes, order DOES matter here, in order to prevent audio from being slightly delayed after peeking with 3D Touch (ugh so tired of that issue)
|
||||||
switch self.emulatorCore.state
|
switch self.emulatorCore.state
|
||||||
{
|
{
|
||||||
case .Stopped:
|
case .stopped:
|
||||||
self.emulatorCore.startEmulation()
|
self.emulatorCore.startEmulation()
|
||||||
self.updateCheats()
|
self.updateCheats()
|
||||||
|
|
||||||
case .Running: break
|
case .running: break
|
||||||
case .Paused:
|
case .paused:
|
||||||
self.updateCheats()
|
self.updateCheats()
|
||||||
self.resumeEmulation()
|
self.resumeEmulation()
|
||||||
}
|
}
|
||||||
@ -177,7 +177,7 @@ class EmulationViewController: UIViewController
|
|||||||
self.controllerViewHeightConstraint.constant = 0
|
self.controllerViewHeightConstraint.constant = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
self.controllerView.hidden = self.isPreviewing
|
self.controllerView.isHidden = self.isPreviewing
|
||||||
}
|
}
|
||||||
|
|
||||||
override func prefersStatusBarHidden() -> Bool
|
override func prefersStatusBarHidden() -> Bool
|
||||||
@ -186,15 +186,15 @@ class EmulationViewController: UIViewController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <UIContentContainer>
|
/// <UIContentContainer>
|
||||||
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
|
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
|
||||||
{
|
{
|
||||||
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
|
super.viewWillTransition(to: size, with: coordinator)
|
||||||
|
|
||||||
self.controllerView.beginAnimatingUpdateControllerSkin()
|
self.controllerView.beginAnimatingUpdateControllerSkin()
|
||||||
|
|
||||||
coordinator.animateAlongsideTransition({ _ in
|
coordinator.animate(alongsideTransition: { _ in
|
||||||
|
|
||||||
if self.emulatorCore.state == .Paused
|
if self.emulatorCore.state == .paused
|
||||||
{
|
{
|
||||||
// We need to manually "refresh" the game screen, otherwise the system tries to cache the rendered image, but skews it incorrectly when rotating b/c of UIVisualEffectView
|
// We need to manually "refresh" the game screen, otherwise the system tries to cache the rendered image, but skews it incorrectly when rotating b/c of UIVisualEffectView
|
||||||
self.gameView.inputImage = self.gameView.outputImage
|
self.gameView.inputImage = self.gameView.outputImage
|
||||||
@ -208,7 +208,7 @@ class EmulationViewController: UIViewController
|
|||||||
// MARK: - Navigation -
|
// MARK: - Navigation -
|
||||||
|
|
||||||
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
||||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
|
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
|
||||||
{
|
{
|
||||||
self.pauseEmulation()
|
self.pauseEmulation()
|
||||||
|
|
||||||
@ -226,11 +226,11 @@ class EmulationViewController: UIViewController
|
|||||||
// As a dirty workaround, we just use a weak reference, and force unwrap it if needed
|
// As a dirty workaround, we just use a weak reference, and force unwrap it if needed
|
||||||
|
|
||||||
let saveStateItem = PauseItem(image: UIImage(named: "SaveSaveState")!, text: NSLocalizedString("Save State", comment: ""), action: { [unowned self] _ in
|
let saveStateItem = PauseItem(image: UIImage(named: "SaveSaveState")!, text: NSLocalizedString("Save State", comment: ""), action: { [unowned self] _ in
|
||||||
pauseViewController.presentSaveStateViewControllerWithMode(.Saving, delegate: self)
|
pauseViewController.presentSaveStateViewControllerWithMode(.saving, delegate: self)
|
||||||
})
|
})
|
||||||
|
|
||||||
let loadStateItem = PauseItem(image: UIImage(named: "LoadSaveState")!, text: NSLocalizedString("Load State", comment: ""), action: { [unowned self] _ in
|
let loadStateItem = PauseItem(image: UIImage(named: "LoadSaveState")!, text: NSLocalizedString("Load State", comment: ""), action: { [unowned self] _ in
|
||||||
pauseViewController.presentSaveStateViewControllerWithMode(.Loading, delegate: self)
|
pauseViewController.presentSaveStateViewControllerWithMode(.loading, delegate: self)
|
||||||
})
|
})
|
||||||
|
|
||||||
let cheatCodesItem = PauseItem(image: UIImage(named: "SmallPause")!, text: NSLocalizedString("Cheat Codes", comment: ""), action: { [unowned self] _ in
|
let cheatCodesItem = PauseItem(image: UIImage(named: "SmallPause")!, text: NSLocalizedString("Cheat Codes", comment: ""), action: { [unowned self] _ in
|
||||||
@ -260,7 +260,7 @@ class EmulationViewController: UIViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func unwindFromPauseViewController(segue: UIStoryboardSegue)
|
@IBAction func unwindFromPauseViewController(_ segue: UIStoryboardSegue)
|
||||||
{
|
{
|
||||||
self.pauseViewController = nil
|
self.pauseViewController = nil
|
||||||
self.pausingGameController = nil
|
self.pausingGameController = nil
|
||||||
@ -271,7 +271,7 @@ class EmulationViewController: UIViewController
|
|||||||
self.emulatorCore.audioManager.enabled = false
|
self.emulatorCore.audioManager.enabled = false
|
||||||
|
|
||||||
// Re-enable after delay
|
// Re-enable after delay
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
|
DispatchQueue.main.after(when: DispatchTime.now() + Double(Int64(0.1 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) {
|
||||||
self.emulatorCore.audioManager.enabled = true
|
self.emulatorCore.audioManager.enabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -288,10 +288,10 @@ class EmulationViewController: UIViewController
|
|||||||
|
|
||||||
let presentingViewController = self.presentingViewController
|
let presentingViewController = self.presentingViewController
|
||||||
|
|
||||||
let launchGameAction = UIPreviewAction(title: NSLocalizedString("Launch \(self.game.name)", comment: ""), style: .Default) { (action, viewController) in
|
let launchGameAction = UIPreviewAction(title: NSLocalizedString("Launch \(self.game.name)", comment: ""), style: .default) { (action, viewController) in
|
||||||
// Delaying until next run loop prevents self from being dismissed immediately
|
// Delaying until next run loop prevents self from being dismissed immediately
|
||||||
dispatch_async(dispatch_get_main_queue()) {
|
DispatchQueue.main.async {
|
||||||
presentingViewController?.presentViewController(viewController, animated: true, completion: nil)
|
presentingViewController?.present(viewController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [launchGameAction]
|
return [launchGameAction]
|
||||||
@ -302,9 +302,9 @@ class EmulationViewController: UIViewController
|
|||||||
/// Emulation
|
/// Emulation
|
||||||
private extension EmulationViewController
|
private extension EmulationViewController
|
||||||
{
|
{
|
||||||
func pause(sender sender: AnyObject?)
|
func pause(sender: AnyObject?)
|
||||||
{
|
{
|
||||||
self.performSegueWithIdentifier("pauseSegue", sender: sender)
|
self.performSegue(withIdentifier: "pauseSegue", sender: sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
func pauseEmulation() -> Bool
|
func pauseEmulation() -> Bool
|
||||||
@ -319,11 +319,11 @@ private extension EmulationViewController
|
|||||||
return self.emulatorCore.resumeEmulation()
|
return self.emulatorCore.resumeEmulation()
|
||||||
}
|
}
|
||||||
|
|
||||||
func emulatorCoreDidUpdate(emulatorCore: EmulatorCore)
|
func emulatorCoreDidUpdate(_ emulatorCore: EmulatorCore)
|
||||||
{
|
{
|
||||||
for semaphore in self.updateSemaphores
|
for semaphore in self.updateSemaphores
|
||||||
{
|
{
|
||||||
dispatch_semaphore_signal(semaphore.semaphore)
|
semaphore.semaphore.signal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -345,7 +345,7 @@ private extension EmulationViewController
|
|||||||
controllers.append(self.controllerView)
|
controllers.append(self.controllerView)
|
||||||
|
|
||||||
// We need to map each item as a GameControllerProtocol due to a Swift bug
|
// We need to map each item as a GameControllerProtocol due to a Swift bug
|
||||||
controllers.appendContentsOf(ExternalControllerManager.sharedManager.connectedControllers.map { $0 as GameControllerProtocol })
|
controllers.append(contentsOf: ExternalControllerManager.sharedManager.connectedControllers.map { $0 as GameControllerProtocol })
|
||||||
|
|
||||||
for controller in controllers
|
for controller in controllers
|
||||||
{
|
{
|
||||||
@ -370,17 +370,17 @@ private extension EmulationViewController
|
|||||||
func showSustainButtonView()
|
func showSustainButtonView()
|
||||||
{
|
{
|
||||||
self.choosingSustainedButtons = true
|
self.choosingSustainedButtons = true
|
||||||
self.sustainButtonContentView.hidden = false
|
self.sustainButtonContentView.isHidden = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func hideSustainButtonView()
|
func hideSustainButtonView()
|
||||||
{
|
{
|
||||||
self.choosingSustainedButtons = false
|
self.choosingSustainedButtons = false
|
||||||
|
|
||||||
UIView.animateWithDuration(0.4, animations: {
|
UIView.animate(withDuration: 0.4, animations: {
|
||||||
self.sustainButtonContentView.alpha = 0.0
|
self.sustainButtonContentView.alpha = 0.0
|
||||||
}) { (finished) in
|
}) { (finished) in
|
||||||
self.sustainButtonContentView.hidden = true
|
self.sustainButtonContentView.isHidden = true
|
||||||
self.sustainButtonContentView.alpha = 1.0
|
self.sustainButtonContentView.alpha = 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -405,7 +405,7 @@ private extension EmulationViewController
|
|||||||
self.sustainedInputs[ObjectIdentifier(gameController)] = []
|
self.sustainedInputs[ObjectIdentifier(gameController)] = []
|
||||||
}
|
}
|
||||||
|
|
||||||
func addSustainedInput(input: InputType, gameController: GameControllerProtocol)
|
func addSustainedInput(_ input: InputType, gameController: GameControllerProtocol)
|
||||||
{
|
{
|
||||||
var inputs = self.sustainedInputs[ObjectIdentifier(gameController)] ?? []
|
var inputs = self.sustainedInputs[ObjectIdentifier(gameController)] ?? []
|
||||||
|
|
||||||
@ -424,10 +424,10 @@ private extension EmulationViewController
|
|||||||
receivers.forEach { gameController.addReceiver($0) }
|
receivers.forEach { gameController.addReceiver($0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
func reactivateSustainedInput(input: InputType, gameController: GameControllerProtocol)
|
func reactivateSustainedInput(_ input: InputType, gameController: GameControllerProtocol)
|
||||||
{
|
{
|
||||||
// These MUST be performed serially, or else Bad Things Happen™ if multiple inputs are reactivated at once
|
// These MUST be performed serially, or else Bad Things Happen™ if multiple inputs are reactivated at once
|
||||||
self.reactivateSustainInputsQueue.addOperationWithBlock {
|
self.reactivateSustainInputsQueue.addOperation {
|
||||||
|
|
||||||
// The manual activations/deactivations here are hidden implementation details, so we won't notify ourselves about them
|
// The manual activations/deactivations here are hidden implementation details, so we won't notify ourselves about them
|
||||||
gameController.removeReceiver(self)
|
gameController.removeReceiver(self)
|
||||||
@ -435,8 +435,8 @@ private extension EmulationViewController
|
|||||||
// Must deactivate first so core recognizes a secondary activation
|
// Must deactivate first so core recognizes a secondary activation
|
||||||
gameController.deactivate(input)
|
gameController.deactivate(input)
|
||||||
|
|
||||||
let dispatchQueue = dispatch_queue_create("com.rileytestut.Delta.sustainButtonsQueue", DISPATCH_QUEUE_SERIAL)
|
let dispatchQueue = DispatchQueue(label: "com.rileytestut.Delta.sustainButtonsQueue", attributes: DispatchQueueAttributes.serial)
|
||||||
dispatch_async(dispatchQueue) {
|
dispatchQueue.async {
|
||||||
|
|
||||||
let semaphore = DispatchSemaphore(value: 0)
|
let semaphore = DispatchSemaphore(value: 0)
|
||||||
self.updateSemaphores.insert(semaphore)
|
self.updateSemaphores.insert(semaphore)
|
||||||
@ -444,11 +444,11 @@ private extension EmulationViewController
|
|||||||
// To ensure the emulator core recognizes us activating the input again, we need to wait at least two frames
|
// To ensure the emulator core recognizes us activating the input again, we need to wait at least two frames
|
||||||
// Unfortunately we cannot init DispatchSemaphore with value less than 0
|
// Unfortunately we cannot init DispatchSemaphore with value less than 0
|
||||||
// To compensate, we simply wait twice; once the first wait returns, we wait again
|
// To compensate, we simply wait twice; once the first wait returns, we wait again
|
||||||
dispatch_semaphore_wait(semaphore.semaphore, DISPATCH_TIME_FOREVER)
|
semaphore.semaphore.wait(timeout: DispatchTime.distantFuture)
|
||||||
dispatch_semaphore_wait(semaphore.semaphore, DISPATCH_TIME_FOREVER)
|
semaphore.semaphore.wait(timeout: DispatchTime.distantFuture)
|
||||||
|
|
||||||
// These MUST be performed serially, or else Bad Things Happen™ if multiple inputs are reactivated at once
|
// These MUST be performed serially, or else Bad Things Happen™ if multiple inputs are reactivated at once
|
||||||
self.reactivateSustainInputsQueue.addOperationWithBlock {
|
self.reactivateSustainInputsQueue.addOperation {
|
||||||
|
|
||||||
self.updateSemaphores.remove(semaphore)
|
self.updateSemaphores.remove(semaphore)
|
||||||
|
|
||||||
@ -481,12 +481,12 @@ private extension EmulationViewController
|
|||||||
/// Save States
|
/// Save States
|
||||||
extension EmulationViewController: SaveStatesViewControllerDelegate
|
extension EmulationViewController: SaveStatesViewControllerDelegate
|
||||||
{
|
{
|
||||||
func saveStatesViewControllerActiveEmulatorCore(saveStatesViewController: SaveStatesViewController) -> EmulatorCore
|
func saveStatesViewControllerActiveEmulatorCore(_ saveStatesViewController: SaveStatesViewController) -> EmulatorCore
|
||||||
{
|
{
|
||||||
return self.emulatorCore
|
return self.emulatorCore
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveStatesViewController(saveStatesViewController: SaveStatesViewController, updateSaveState saveState: SaveState)
|
func saveStatesViewController(_ saveStatesViewController: SaveStatesViewController, updateSaveState saveState: SaveState)
|
||||||
{
|
{
|
||||||
guard let filepath = saveState.fileURL.path else { return }
|
guard let filepath = saveState.fileURL.path else { return }
|
||||||
|
|
||||||
@ -495,13 +495,13 @@ extension EmulationViewController: SaveStatesViewControllerDelegate
|
|||||||
self.emulatorCore.saveSaveState { temporarySaveState in
|
self.emulatorCore.saveSaveState { temporarySaveState in
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if NSFileManager.defaultManager().fileExistsAtPath(filepath)
|
if FileManager.default.fileExists(atPath: filepath)
|
||||||
{
|
{
|
||||||
try NSFileManager.defaultManager().replaceItemAtURL(saveState.fileURL, withItemAtURL: temporarySaveState.fileURL, backupItemName: nil, options: [], resultingItemURL: nil)
|
try FileManager.default.replaceItem(at: saveState.fileURL, withItemAt: temporarySaveState.fileURL, backupItemName: nil, options: [], resultingItemURL: nil)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
try NSFileManager.defaultManager().moveItemAtURL(temporarySaveState.fileURL, toURL: saveState.fileURL)
|
try FileManager.default.moveItem(at: temporarySaveState.fileURL, to: saveState.fileURL)
|
||||||
|
|
||||||
updatingExistingSaveState = false
|
updatingExistingSaveState = false
|
||||||
}
|
}
|
||||||
@ -514,13 +514,13 @@ extension EmulationViewController: SaveStatesViewControllerDelegate
|
|||||||
|
|
||||||
if let outputImage = self.gameView.outputImage
|
if let outputImage = self.gameView.outputImage
|
||||||
{
|
{
|
||||||
let quartzImage = self.context.createCGImage(outputImage, fromRect: outputImage.extent)
|
let quartzImage = self.context.createCGImage(outputImage, from: outputImage.extent)
|
||||||
|
|
||||||
let image = UIImage(CGImage: quartzImage)
|
let image = UIImage(cgImage: quartzImage)
|
||||||
UIImagePNGRepresentation(image)?.writeToURL(saveState.imageFileURL, atomically: true)
|
try? UIImagePNGRepresentation(image)?.write(to: saveState.imageFileURL, options: [.dataWritingAtomic])
|
||||||
}
|
}
|
||||||
|
|
||||||
saveState.modifiedDate = NSDate()
|
saveState.modifiedDate = Date()
|
||||||
|
|
||||||
// Dismiss if updating an existing save state.
|
// Dismiss if updating an existing save state.
|
||||||
// If creating a new one, don't dismiss.
|
// If creating a new one, don't dismiss.
|
||||||
@ -530,7 +530,7 @@ extension EmulationViewController: SaveStatesViewControllerDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveStatesViewController(saveStatesViewController: SaveStatesViewController, loadSaveState saveState: SaveStateType)
|
func saveStatesViewController(_ saveStatesViewController: SaveStatesViewController, loadSaveState saveState: SaveStateType)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -555,17 +555,17 @@ extension EmulationViewController: SaveStatesViewControllerDelegate
|
|||||||
/// Cheats
|
/// Cheats
|
||||||
extension EmulationViewController: CheatsViewControllerDelegate
|
extension EmulationViewController: CheatsViewControllerDelegate
|
||||||
{
|
{
|
||||||
func cheatsViewControllerActiveEmulatorCore(saveStatesViewController: CheatsViewController) -> EmulatorCore
|
func cheatsViewControllerActiveEmulatorCore(_ saveStatesViewController: CheatsViewController) -> EmulatorCore
|
||||||
{
|
{
|
||||||
return self.emulatorCore
|
return self.emulatorCore
|
||||||
}
|
}
|
||||||
|
|
||||||
func cheatsViewController(cheatsViewController: CheatsViewController, didActivateCheat cheat: Cheat) throws
|
func cheatsViewController(_ cheatsViewController: CheatsViewController, didActivateCheat cheat: Cheat) throws
|
||||||
{
|
{
|
||||||
try self.emulatorCore.activateCheat(cheat)
|
try self.emulatorCore.activateCheat(cheat)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cheatsViewController(cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat)
|
func cheatsViewController(_ cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat)
|
||||||
{
|
{
|
||||||
self.emulatorCore.deactivateCheat(cheat)
|
self.emulatorCore.deactivateCheat(cheat)
|
||||||
}
|
}
|
||||||
@ -573,9 +573,9 @@ extension EmulationViewController: CheatsViewControllerDelegate
|
|||||||
private func updateCheats()
|
private func updateCheats()
|
||||||
{
|
{
|
||||||
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
backgroundContext.performBlockAndWait {
|
backgroundContext.performAndWait {
|
||||||
|
|
||||||
let running = (self.emulatorCore.state == .Running)
|
let running = (self.emulatorCore.state == .running)
|
||||||
|
|
||||||
if running
|
if running
|
||||||
{
|
{
|
||||||
@ -583,7 +583,7 @@ extension EmulationViewController: CheatsViewControllerDelegate
|
|||||||
self.pauseEmulation()
|
self.pauseEmulation()
|
||||||
}
|
}
|
||||||
|
|
||||||
let predicate = NSPredicate(format: "%K == %@", Cheat.Attributes.game.rawValue, self.emulatorCore.game as! Game)
|
let predicate = Predicate(format: "%K == %@", Cheat.Attributes.game.rawValue, self.emulatorCore.game as! Game)
|
||||||
|
|
||||||
let cheats = Cheat.instancesWithPredicate(predicate, inManagedObjectContext: backgroundContext, type: Cheat.self)
|
let cheats = Cheat.instancesWithPredicate(predicate, inManagedObjectContext: backgroundContext, type: Cheat.self)
|
||||||
for cheat in cheats
|
for cheat in cheats
|
||||||
@ -623,12 +623,12 @@ extension EmulationViewController: CheatsViewControllerDelegate
|
|||||||
//MARK: - App Lifecycle -
|
//MARK: - App Lifecycle -
|
||||||
private extension EmulationViewController
|
private extension EmulationViewController
|
||||||
{
|
{
|
||||||
@objc func willResignActive(notification: NSNotification)
|
@objc func willResignActive(_ notification: Notification)
|
||||||
{
|
{
|
||||||
self.pauseEmulation()
|
self.pauseEmulation()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func didBecomeActive(notification: NSNotification)
|
@objc func didBecomeActive(_ notification: Notification)
|
||||||
{
|
{
|
||||||
self.resumeEmulation()
|
self.resumeEmulation()
|
||||||
}
|
}
|
||||||
@ -638,18 +638,18 @@ private extension EmulationViewController
|
|||||||
/// <GameControllerReceiver>
|
/// <GameControllerReceiver>
|
||||||
extension EmulationViewController: GameControllerReceiverProtocol
|
extension EmulationViewController: GameControllerReceiverProtocol
|
||||||
{
|
{
|
||||||
func gameController(gameController: GameControllerProtocol, didActivateInput input: InputType)
|
func gameController(_ gameController: GameControllerProtocol, didActivateInput input: InputType)
|
||||||
{
|
{
|
||||||
if gameController is ControllerView && UIDevice.currentDevice().supportsVibration
|
if gameController is ControllerView && UIDevice.current().isVibrationSupported
|
||||||
{
|
{
|
||||||
UIDevice.currentDevice().vibrate()
|
UIDevice.current().vibrate()
|
||||||
}
|
}
|
||||||
|
|
||||||
if let input = input as? ControllerInput
|
if let input = input as? ControllerInput
|
||||||
{
|
{
|
||||||
switch input
|
switch input
|
||||||
{
|
{
|
||||||
case ControllerInput.Menu:
|
case ControllerInput.menu:
|
||||||
if self.choosingSustainedButtons { self.hideSustainButtonView() }
|
if self.choosingSustainedButtons { self.hideSustainButtonView() }
|
||||||
self.pause(sender: gameController)
|
self.pause(sender: gameController)
|
||||||
|
|
||||||
@ -667,7 +667,7 @@ extension EmulationViewController: GameControllerReceiverProtocol
|
|||||||
if let sustainedInputs = self.sustainedInputs[ObjectIdentifier(gameController)] where sustainedInputs.contains({ $0.isEqual(input) })
|
if let sustainedInputs = self.sustainedInputs[ObjectIdentifier(gameController)] where sustainedInputs.contains({ $0.isEqual(input) })
|
||||||
{
|
{
|
||||||
// Perform on next run loop
|
// Perform on next run loop
|
||||||
dispatch_async(dispatch_get_main_queue()) {
|
DispatchQueue.main.async {
|
||||||
self.reactivateSustainedInput(input, gameController: gameController)
|
self.reactivateSustainedInput(input, gameController: gameController)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,7 +675,7 @@ extension EmulationViewController: GameControllerReceiverProtocol
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func gameController(gameController: GameControllerProtocol, didDeactivateInput input: InputType)
|
func gameController(_ gameController: GameControllerProtocol, didDeactivateInput input: InputType)
|
||||||
{
|
{
|
||||||
guard let input = input as? ControllerInput else { return }
|
guard let input = input as? ControllerInput else { return }
|
||||||
|
|
||||||
|
|||||||
@ -18,8 +18,8 @@ internal extension UILabel
|
|||||||
context.minimumScaleFactor = self.minimumScaleFactor
|
context.minimumScaleFactor = self.minimumScaleFactor
|
||||||
|
|
||||||
// Using self.attributedString returns incorrect calculations, so we create our own attributed string
|
// Using self.attributedString returns incorrect calculations, so we create our own attributed string
|
||||||
let attributedString = NSAttributedString(string: text, attributes: [NSFontAttributeName: self.font])
|
let attributedString = AttributedString(string: text, attributes: [NSFontAttributeName: self.font])
|
||||||
attributedString.boundingRectWithSize(self.bounds.size, options: [.UsesLineFragmentOrigin, .UsesFontLeading], context: context)
|
attributedString.boundingRect(with: self.bounds.size, options: [.usesLineFragmentOrigin, .usesFontLeading], context: context)
|
||||||
|
|
||||||
let scaleFactor = context.actualScaleFactor
|
let scaleFactor = context.actualScaleFactor
|
||||||
return scaleFactor
|
return scaleFactor
|
||||||
|
|||||||
@ -13,6 +13,6 @@ extension UIViewController
|
|||||||
var isPreviewing: Bool
|
var isPreviewing: Bool
|
||||||
{
|
{
|
||||||
guard let presentationController = self.presentationController else { return false }
|
guard let presentationController = self.presentationController else { return false }
|
||||||
return NSStringFromClass(presentationController.dynamicType).containsString("PreviewPresentation")
|
return NSStringFromClass(presentationController.dynamicType).contains("PreviewPresentation")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ class GamesCollectionViewController: UICollectionViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(animated: Bool)
|
override func viewWillAppear(_ animated: Bool)
|
||||||
{
|
{
|
||||||
self.dataSource.update()
|
self.dataSource.update()
|
||||||
|
|
||||||
@ -62,14 +62,14 @@ class GamesCollectionViewController: UICollectionViewController
|
|||||||
// MARK: - Navigation -
|
// MARK: - Navigation -
|
||||||
|
|
||||||
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
||||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
|
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
|
||||||
{
|
{
|
||||||
self.segueHandler?.prepareForSegue(segue, sender: sender)
|
self.segueHandler?.prepare(for: segue, sender: sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Collection View -
|
// MARK: - Collection View -
|
||||||
|
|
||||||
private func configureCell(cell: GridCollectionViewCell, game: Game)
|
private func configureCell(_ cell: GridCollectionViewCell, game: Game)
|
||||||
{
|
{
|
||||||
cell.maximumImageSize = CGSize(width: 90, height: 90)
|
cell.maximumImageSize = CGSize(width: 90, height: 90)
|
||||||
cell.textLabel.text = game.name
|
cell.textLabel.text = game.name
|
||||||
@ -79,7 +79,7 @@ class GamesCollectionViewController: UICollectionViewController
|
|||||||
|
|
||||||
extension GamesCollectionViewController: NSFetchedResultsControllerDelegate
|
extension GamesCollectionViewController: NSFetchedResultsControllerDelegate
|
||||||
{
|
{
|
||||||
func controllerDidChangeContent(controller: NSFetchedResultsController)
|
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
|
||||||
{
|
{
|
||||||
self.collectionView?.reloadData()
|
self.collectionView?.reloadData()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,16 +19,16 @@ class GamesViewController: UIViewController
|
|||||||
private var backgroundView: RSTBackgroundView!
|
private var backgroundView: RSTBackgroundView!
|
||||||
private var pageControl: UIPageControl!
|
private var pageControl: UIPageControl!
|
||||||
|
|
||||||
private let fetchedResultsController: NSFetchedResultsController
|
private let fetchedResultsController: NSFetchedResultsController<AnyObject>
|
||||||
|
|
||||||
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
|
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
|
||||||
fatalError("initWithNibName: not implemented")
|
fatalError("initWithNibName: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder)
|
required init?(coder aDecoder: NSCoder)
|
||||||
{
|
{
|
||||||
let fetchRequest = GameCollection.fetchRequest()
|
let fetchRequest = GameCollection.fetchRequest()
|
||||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: GameCollection.Attributes.index.rawValue, ascending: true)]
|
fetchRequest.sortDescriptors = [SortDescriptor(key: GameCollection.Attributes.index.rawValue, ascending: true)]
|
||||||
|
|
||||||
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
|
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
|
||||||
|
|
||||||
@ -44,29 +44,29 @@ class GamesViewController: UIViewController
|
|||||||
self.automaticallyAdjustsScrollViewInsets = false
|
self.automaticallyAdjustsScrollViewInsets = false
|
||||||
|
|
||||||
self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
|
self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
|
||||||
self.backgroundView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
|
self.backgroundView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||||
self.backgroundView.textLabel.text = NSLocalizedString("No Games", comment: "")
|
self.backgroundView.textLabel.text = NSLocalizedString("No Games", comment: "")
|
||||||
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can import games by pressing the + button in the top right.", comment: "")
|
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can import games by pressing the + button in the top right.", comment: "")
|
||||||
self.view.insertSubview(self.backgroundView, atIndex: 0)
|
self.view.insertSubview(self.backgroundView, at: 0)
|
||||||
|
|
||||||
self.pageViewController = self.childViewControllers.first as? UIPageViewController
|
self.pageViewController = self.childViewControllers.first as? UIPageViewController
|
||||||
self.pageViewController.dataSource = self
|
self.pageViewController.dataSource = self
|
||||||
self.pageViewController.delegate = self
|
self.pageViewController.delegate = self
|
||||||
self.pageViewController.view.hidden = true
|
self.pageViewController.view.isHidden = true
|
||||||
|
|
||||||
self.pageControl = UIPageControl()
|
self.pageControl = UIPageControl()
|
||||||
self.pageControl.translatesAutoresizingMaskIntoConstraints = false
|
self.pageControl.translatesAutoresizingMaskIntoConstraints = false
|
||||||
self.pageControl.hidesForSinglePage = false
|
self.pageControl.hidesForSinglePage = false
|
||||||
self.pageControl.numberOfPages = 3
|
self.pageControl.numberOfPages = 3
|
||||||
self.pageControl.currentPageIndicatorTintColor = UIColor.purpleColor()
|
self.pageControl.currentPageIndicatorTintColor = UIColor.purple()
|
||||||
self.pageControl.pageIndicatorTintColor = UIColor.lightGrayColor()
|
self.pageControl.pageIndicatorTintColor = UIColor.lightGray()
|
||||||
self.navigationController?.toolbar.addSubview(self.pageControl)
|
self.navigationController?.toolbar.addSubview(self.pageControl)
|
||||||
|
|
||||||
self.pageControl.centerXAnchor.constraintEqualToAnchor(self.navigationController?.toolbar.centerXAnchor, constant: 0).active = true
|
self.pageControl.centerXAnchor.constraint(equalTo: (self.navigationController?.toolbar.centerXAnchor)!, constant: 0).isActive = true
|
||||||
self.pageControl.centerYAnchor.constraintEqualToAnchor(self.navigationController?.toolbar.centerYAnchor, constant: 0).active = true
|
self.pageControl.centerYAnchor.constraint(equalTo: (self.navigationController?.toolbar.centerYAnchor)!, constant: 0).isActive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(animated: Bool)
|
override func viewWillAppear(_ animated: Bool)
|
||||||
{
|
{
|
||||||
super.viewWillAppear(animated)
|
super.viewWillAppear(animated)
|
||||||
|
|
||||||
@ -115,14 +115,14 @@ class GamesViewController: UIViewController
|
|||||||
// MARK: - Navigation -
|
// MARK: - Navigation -
|
||||||
|
|
||||||
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
||||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
|
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
|
||||||
{
|
{
|
||||||
guard let sourceViewController = segue.sourceViewController as? GamesCollectionViewController else { return }
|
guard let sourceViewController = segue.sourceViewController as? GamesCollectionViewController else { return }
|
||||||
guard let destinationViewController = segue.destinationViewController as? EmulationViewController else { return }
|
guard let destinationViewController = segue.destinationViewController as? EmulationViewController else { return }
|
||||||
guard let cell = sender as? UICollectionViewCell else { return }
|
guard let cell = sender as? UICollectionViewCell else { return }
|
||||||
|
|
||||||
let indexPath = sourceViewController.collectionView?.indexPathForCell(cell)
|
let indexPath = sourceViewController.collectionView?.indexPath(for: cell)
|
||||||
let game = sourceViewController.dataSource.fetchedResultsController.objectAtIndexPath(indexPath!) as! Game
|
let game = sourceViewController.dataSource.fetchedResultsController.object(at: indexPath!) as! Game
|
||||||
|
|
||||||
destinationViewController.game = game
|
destinationViewController.game = game
|
||||||
|
|
||||||
@ -153,12 +153,12 @@ class GamesViewController: UIViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func unwindFromSettingsViewController(segue: UIStoryboardSegue)
|
@IBAction func unwindFromSettingsViewController(_ segue: UIStoryboardSegue)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func unwindFromEmulationViewController(segue: UIStoryboardSegue)
|
@IBAction func unwindFromEmulationViewController(_ segue: UIStoryboardSegue)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ class GamesViewController: UIViewController
|
|||||||
|
|
||||||
private extension GamesViewController
|
private extension GamesViewController
|
||||||
{
|
{
|
||||||
func viewControllerForIndex(index: Int) -> GamesCollectionViewController?
|
func viewControllerForIndex(_ index: Int) -> GamesCollectionViewController?
|
||||||
{
|
{
|
||||||
guard let pages = self.fetchedResultsController.sections?.first?.numberOfObjects where pages > 0 else { return nil }
|
guard let pages = self.fetchedResultsController.sections?.first?.numberOfObjects where pages > 0 else { return nil }
|
||||||
|
|
||||||
@ -179,10 +179,10 @@ private extension GamesViewController
|
|||||||
safeIndex = pages + safeIndex
|
safeIndex = pages + safeIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
let indexPath = NSIndexPath(forRow: safeIndex, inSection: 0)
|
let indexPath = IndexPath(row: safeIndex, section: 0)
|
||||||
|
|
||||||
let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("gamesCollectionViewController") as! GamesCollectionViewController
|
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "gamesCollectionViewController") as! GamesCollectionViewController
|
||||||
viewController.gameCollection = self.fetchedResultsController.objectAtIndexPath(indexPath) as! GameCollection
|
viewController.gameCollection = self.fetchedResultsController.object(at: indexPath) as! GameCollection
|
||||||
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
|
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
|
||||||
viewController.segueHandler = self
|
viewController.segueHandler = self
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ private extension GamesViewController
|
|||||||
|
|
||||||
if let viewController = pageViewController.viewControllers?.first as? GamesCollectionViewController, let gameCollection = viewController.gameCollection
|
if let viewController = pageViewController.viewControllers?.first as? GamesCollectionViewController, let gameCollection = viewController.gameCollection
|
||||||
{
|
{
|
||||||
if let index = self.fetchedResultsController.fetchedObjects?.indexOf({ $0 as! GameCollection == gameCollection })
|
if let index = self.fetchedResultsController.fetchedObjects?.index(where: { $0 as! GameCollection == gameCollection })
|
||||||
{
|
{
|
||||||
self.pageControl.currentPage = index
|
self.pageControl.currentPage = index
|
||||||
}
|
}
|
||||||
@ -216,31 +216,31 @@ private extension GamesViewController
|
|||||||
if sections > 0
|
if sections > 0
|
||||||
{
|
{
|
||||||
// Reset page view controller if currently hidden or current child should view controller no longer exists
|
// Reset page view controller if currently hidden or current child should view controller no longer exists
|
||||||
if self.pageViewController.view.hidden || resetPageViewController
|
if self.pageViewController.view.isHidden || resetPageViewController
|
||||||
{
|
{
|
||||||
if let viewController = self.viewControllerForIndex(0)
|
if let viewController = self.viewControllerForIndex(0)
|
||||||
{
|
{
|
||||||
self.pageViewController.view.hidden = false
|
self.pageViewController.view.isHidden = false
|
||||||
self.backgroundView.hidden = true
|
self.backgroundView.isHidden = true
|
||||||
|
|
||||||
self.pageViewController.setViewControllers([viewController], direction: .Forward, animated: false, completion: nil)
|
self.pageViewController.setViewControllers([viewController], direction: .forward, animated: false, completion: nil)
|
||||||
|
|
||||||
self.title = viewController.title
|
self.title = viewController.title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self.pageViewController.setViewControllers(self.pageViewController.viewControllers, direction: .Forward, animated: false, completion: nil)
|
self.pageViewController.setViewControllers(self.pageViewController.viewControllers, direction: .forward, animated: false, completion: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self.title = NSLocalizedString("Games", comment: "")
|
self.title = NSLocalizedString("Games", comment: "")
|
||||||
|
|
||||||
if !self.pageViewController.view.hidden
|
if !self.pageViewController.view.isHidden
|
||||||
{
|
{
|
||||||
self.pageViewController.view.hidden = true
|
self.pageViewController.view.isHidden = true
|
||||||
self.backgroundView.hidden = false
|
self.backgroundView.isHidden = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,7 +248,7 @@ private extension GamesViewController
|
|||||||
|
|
||||||
extension GamesViewController: GamePickerControllerDelegate
|
extension GamesViewController: GamePickerControllerDelegate
|
||||||
{
|
{
|
||||||
func gamePickerController(gamePickerController: GamePickerController, didImportGames games: [Game])
|
func gamePickerController(_ gamePickerController: GamePickerController, didImportGames games: [Game])
|
||||||
{
|
{
|
||||||
print(games)
|
print(games)
|
||||||
}
|
}
|
||||||
@ -256,23 +256,23 @@ extension GamesViewController: GamePickerControllerDelegate
|
|||||||
|
|
||||||
extension GamesViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource
|
extension GamesViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource
|
||||||
{
|
{
|
||||||
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
|
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?
|
||||||
{
|
{
|
||||||
let viewController = self.viewControllerForIndex(self.pageControl.currentPage - 1)
|
let viewController = self.viewControllerForIndex(self.pageControl.currentPage - 1)
|
||||||
return viewController
|
return viewController
|
||||||
}
|
}
|
||||||
|
|
||||||
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController?
|
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?
|
||||||
{
|
{
|
||||||
let viewController = self.viewControllerForIndex(self.pageControl.currentPage + 1)
|
let viewController = self.viewControllerForIndex(self.pageControl.currentPage + 1)
|
||||||
return viewController
|
return viewController
|
||||||
}
|
}
|
||||||
|
|
||||||
func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool)
|
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool)
|
||||||
{
|
{
|
||||||
if let viewController = pageViewController.viewControllers?.first as? GamesCollectionViewController, let gameCollection = viewController.gameCollection
|
if let viewController = pageViewController.viewControllers?.first as? GamesCollectionViewController, let gameCollection = viewController.gameCollection
|
||||||
{
|
{
|
||||||
let index = self.fetchedResultsController.fetchedObjects?.indexOf({ $0 as! GameCollection == gameCollection }) ?? 0
|
let index = self.fetchedResultsController.fetchedObjects?.index(where: { $0 as! GameCollection == gameCollection }) ?? 0
|
||||||
self.pageControl.currentPage = index
|
self.pageControl.currentPage = index
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +282,7 @@ extension GamesViewController: UIPageViewControllerDelegate, UIPageViewControlle
|
|||||||
|
|
||||||
extension GamesViewController: NSFetchedResultsControllerDelegate
|
extension GamesViewController: NSFetchedResultsControllerDelegate
|
||||||
{
|
{
|
||||||
func controllerDidChangeContent(controller: NSFetchedResultsController)
|
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
|
||||||
{
|
{
|
||||||
self.updateSections()
|
self.updateSections()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class CheatTextView: UITextView
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NSCopying private var attributedFormat: NSAttributedString?
|
@NSCopying private var attributedFormat: AttributedString?
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder)
|
required init?(coder aDecoder: NSCoder)
|
||||||
{
|
{
|
||||||
@ -44,7 +44,7 @@ extension CheatTextView
|
|||||||
|
|
||||||
if let format = self.cheatFormat, font = self.font
|
if let format = self.cheatFormat, font = self.font
|
||||||
{
|
{
|
||||||
let characterWidth = ("A" as NSString).sizeWithAttributes([NSFontAttributeName: font]).width
|
let characterWidth = ("A" as NSString).size(attributes: [NSFontAttributeName: font]).width
|
||||||
|
|
||||||
let width = characterWidth * CGFloat(format.format.characters.count)
|
let width = characterWidth * CGFloat(format.format.characters.count)
|
||||||
self.textContainer.size = CGSize(width: width, height: 0)
|
self.textContainer.size = CGSize(width: width, height: 0)
|
||||||
@ -65,13 +65,13 @@ private extension CheatTextView
|
|||||||
let attributedFormat = NSMutableAttributedString()
|
let attributedFormat = NSMutableAttributedString()
|
||||||
var prefixString: NSString? = nil
|
var prefixString: NSString? = nil
|
||||||
|
|
||||||
let scanner = NSScanner(string: format)
|
let scanner = Scanner(string: format)
|
||||||
scanner.charactersToBeSkipped = nil
|
scanner.charactersToBeSkipped = nil
|
||||||
|
|
||||||
while (!scanner.atEnd)
|
while (!scanner.isAtEnd)
|
||||||
{
|
{
|
||||||
var string: NSString? = nil
|
var string: NSString? = nil
|
||||||
scanner.scanCharactersFromSet(NSCharacterSet.alphanumericCharacterSet(), intoString: &string)
|
scanner.scanCharacters(from: CharacterSet.alphanumerics, into: &string)
|
||||||
|
|
||||||
guard let scannedString = string where scannedString.length > 0 else { break }
|
guard let scannedString = string where scannedString.length > 0 else { break }
|
||||||
|
|
||||||
@ -82,10 +82,10 @@ private extension CheatTextView
|
|||||||
attributedString.addAttribute(CheatPrefixAttribute, value: prefixString, range: NSRange(location: 0, length: 1))
|
attributedString.addAttribute(CheatPrefixAttribute, value: prefixString, range: NSRange(location: 0, length: 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
attributedFormat.appendAttributedString(attributedString)
|
attributedFormat.append(attributedString)
|
||||||
|
|
||||||
prefixString = nil
|
prefixString = nil
|
||||||
scanner.scanUpToCharactersFromSet(NSCharacterSet.alphanumericCharacterSet(), intoString: &prefixString)
|
scanner.scanUpToCharacters(from: CharacterSet.alphanumerics, into: &prefixString)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.attributedFormat = attributedFormat
|
self.attributedFormat = attributedFormat
|
||||||
@ -95,17 +95,17 @@ private extension CheatTextView
|
|||||||
self.layoutIfNeeded()
|
self.layoutIfNeeded()
|
||||||
|
|
||||||
let range = NSRange(location: 0, length: (self.text as NSString).length)
|
let range = NSRange(location: 0, length: (self.text as NSString).length)
|
||||||
self.layoutManager.invalidateGlyphsForCharacterRange(range, changeInLength: 0, actualCharacterRange: nil)
|
self.layoutManager.invalidateGlyphs(forCharacterRange: range, changeInLength: 0, actualCharacterRange: nil)
|
||||||
self.layoutManager.invalidateLayoutForCharacterRange(range, actualCharacterRange: nil)
|
self.layoutManager.invalidateLayout(forCharacterRange: range, actualCharacterRange: nil)
|
||||||
self.layoutManager.ensureGlyphsForCharacterRange(range)
|
self.layoutManager.ensureGlyphs(forCharacterRange: range)
|
||||||
self.layoutManager.ensureLayoutForCharacterRange(range)
|
self.layoutManager.ensureLayout(forCharacterRange: range)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension CheatTextView: NSLayoutManagerDelegate
|
extension CheatTextView: NSLayoutManagerDelegate
|
||||||
{
|
{
|
||||||
func layoutManager(layoutManager: NSLayoutManager, shouldGenerateGlyphs glyphs: UnsafePointer<CGGlyph>, properties props: UnsafePointer<NSGlyphProperty>, characterIndexes charIndexes: UnsafePointer<Int>, font aFont: UIFont, forGlyphRange glyphRange: NSRange) -> Int
|
func layoutManager(_ layoutManager: NSLayoutManager, shouldGenerateGlyphs glyphs: UnsafePointer<CGGlyph>, properties props: UnsafePointer<NSGlyphProperty>, characterIndexes charIndexes: UnsafePointer<Int>, font aFont: UIFont, forGlyphRange glyphRange: NSRange) -> Int
|
||||||
{
|
{
|
||||||
// Returning 0 = let the layoutManager do the normal logic
|
// Returning 0 = let the layoutManager do the normal logic
|
||||||
guard let attributedFormat = self.attributedFormat else { return 0 }
|
guard let attributedFormat = self.attributedFormat else { return 0 }
|
||||||
@ -117,9 +117,9 @@ extension CheatTextView: NSLayoutManagerDelegate
|
|||||||
let bufferSize = max(attributedFormat.length + 1, glyphCount * 2)
|
let bufferSize = max(attributedFormat.length + 1, glyphCount * 2)
|
||||||
|
|
||||||
// Allocate our replacement buffers
|
// Allocate our replacement buffers
|
||||||
let glyphBuffer = UnsafeMutablePointer<CGGlyph>.alloc(bufferSize)
|
let glyphBuffer = UnsafeMutablePointer<CGGlyph>(allocatingCapacity: bufferSize)
|
||||||
let propertyBuffer = UnsafeMutablePointer<NSGlyphProperty>.alloc(bufferSize)
|
let propertyBuffer = UnsafeMutablePointer<NSGlyphProperty>(allocatingCapacity: bufferSize)
|
||||||
let characterBuffer = UnsafeMutablePointer<Int>.alloc(bufferSize)
|
let characterBuffer = UnsafeMutablePointer<Int>(allocatingCapacity: bufferSize)
|
||||||
|
|
||||||
var offset = 0
|
var offset = 0
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ extension CheatTextView: NSLayoutManagerDelegate
|
|||||||
// The index the actual character maps to in the cheat format
|
// The index the actual character maps to in the cheat format
|
||||||
let characterIndex = charIndexes[i] % attributedFormat.length
|
let characterIndex = charIndexes[i] % attributedFormat.length
|
||||||
|
|
||||||
if let prefix = attributedFormat.attributesAtIndex(characterIndex, effectiveRange: nil)[CheatPrefixAttribute] as? String
|
if let prefix = attributedFormat.attributes(at: characterIndex, effectiveRange: nil)[CheatPrefixAttribute] as? String
|
||||||
{
|
{
|
||||||
// If there is a prefix string, we insert the glyphs (and associated properties/character indexes) first
|
// If there is a prefix string, we insert the glyphs (and associated properties/character indexes) first
|
||||||
let prefixCount = prefix.characters.count
|
let prefixCount = prefix.characters.count
|
||||||
@ -139,7 +139,7 @@ extension CheatTextView: NSLayoutManagerDelegate
|
|||||||
propertyBuffer[i + offset + j] = props[i]
|
propertyBuffer[i + offset + j] = props[i]
|
||||||
|
|
||||||
// Prepend prefix character
|
// Prepend prefix character
|
||||||
var prefixCharacter = (prefix as NSString).characterAtIndex(0)
|
var prefixCharacter = (prefix as NSString).character(at: 0)
|
||||||
CTFontGetGlyphsForCharacters(aFont as CTFont, &prefixCharacter, glyphBuffer + (i + offset + j), 1)
|
CTFontGetGlyphsForCharacters(aFont as CTFont, &prefixCharacter, glyphBuffer + (i + offset + j), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,9 +156,9 @@ extension CheatTextView: NSLayoutManagerDelegate
|
|||||||
layoutManager.setGlyphs(glyphBuffer, properties: propertyBuffer, characterIndexes: characterBuffer, font: aFont, forGlyphRange: NSRange(location: glyphRange.location, length: glyphCount + offset))
|
layoutManager.setGlyphs(glyphBuffer, properties: propertyBuffer, characterIndexes: characterBuffer, font: aFont, forGlyphRange: NSRange(location: glyphRange.location, length: glyphCount + offset))
|
||||||
|
|
||||||
// Clean up memory
|
// Clean up memory
|
||||||
characterBuffer.dealloc(bufferSize)
|
characterBuffer.deallocateCapacity(bufferSize)
|
||||||
propertyBuffer.dealloc(bufferSize)
|
propertyBuffer.deallocateCapacity(bufferSize)
|
||||||
glyphBuffer.dealloc(bufferSize)
|
glyphBuffer.deallocateCapacity(bufferSize)
|
||||||
|
|
||||||
// Return total number of glyphs
|
// Return total number of glyphs
|
||||||
return glyphCount + offset
|
return glyphCount + offset
|
||||||
|
|||||||
@ -15,9 +15,9 @@ import Roxas
|
|||||||
|
|
||||||
protocol CheatsViewControllerDelegate: class
|
protocol CheatsViewControllerDelegate: class
|
||||||
{
|
{
|
||||||
func cheatsViewControllerActiveEmulatorCore(saveStatesViewController: CheatsViewController) -> EmulatorCore
|
func cheatsViewControllerActiveEmulatorCore(_ saveStatesViewController: CheatsViewController) -> EmulatorCore
|
||||||
func cheatsViewController(cheatsViewController: CheatsViewController, didActivateCheat cheat: Cheat) throws
|
func cheatsViewController(_ cheatsViewController: CheatsViewController, didActivateCheat cheat: Cheat) throws
|
||||||
func cheatsViewController(cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat)
|
func cheatsViewController(_ cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat)
|
||||||
}
|
}
|
||||||
|
|
||||||
class CheatsViewController: UITableViewController
|
class CheatsViewController: UITableViewController
|
||||||
@ -30,7 +30,7 @@ class CheatsViewController: UITableViewController
|
|||||||
|
|
||||||
private var backgroundView: RSTBackgroundView!
|
private var backgroundView: RSTBackgroundView!
|
||||||
|
|
||||||
private var fetchedResultsController: NSFetchedResultsController!
|
private var fetchedResultsController: NSFetchedResultsController<AnyObject>!
|
||||||
}
|
}
|
||||||
|
|
||||||
extension CheatsViewController
|
extension CheatsViewController
|
||||||
@ -42,18 +42,18 @@ extension CheatsViewController
|
|||||||
self.title = NSLocalizedString("Cheats", comment: "")
|
self.title = NSLocalizedString("Cheats", comment: "")
|
||||||
|
|
||||||
self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
|
self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
|
||||||
self.backgroundView.hidden = false
|
self.backgroundView.isHidden = false
|
||||||
self.backgroundView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
|
self.backgroundView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||||
self.backgroundView.textLabel.text = NSLocalizedString("No Cheats", comment: "")
|
self.backgroundView.textLabel.text = NSLocalizedString("No Cheats", comment: "")
|
||||||
self.backgroundView.textLabel.textColor = UIColor.whiteColor()
|
self.backgroundView.textLabel.textColor = UIColor.white()
|
||||||
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can add a new cheat by pressing the + button in the top right.", comment: "")
|
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can add a new cheat by pressing the + button in the top right.", comment: "")
|
||||||
self.backgroundView.detailTextLabel.textColor = UIColor.whiteColor()
|
self.backgroundView.detailTextLabel.textColor = UIColor.white()
|
||||||
self.tableView.backgroundView = self.backgroundView
|
self.tableView.backgroundView = self.backgroundView
|
||||||
|
|
||||||
self.registerForPreviewingWithDelegate(self, sourceView: self.tableView)
|
self.registerForPreviewing(with: self, sourceView: self.tableView)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(animated: Bool)
|
override func viewWillAppear(_ animated: Bool)
|
||||||
{
|
{
|
||||||
self.fetchedResultsController.performFetchIfNeeded()
|
self.fetchedResultsController.performFetchIfNeeded()
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ extension CheatsViewController
|
|||||||
//MARK: - Navigation -
|
//MARK: - Navigation -
|
||||||
private extension CheatsViewController
|
private extension CheatsViewController
|
||||||
{
|
{
|
||||||
@IBAction func unwindFromEditCheatViewController(segue: UIStoryboardSegue)
|
@IBAction func unwindFromEditCheatViewController(_ segue: UIStoryboardSegue)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -87,8 +87,8 @@ private extension CheatsViewController
|
|||||||
|
|
||||||
let fetchRequest = Cheat.fetchRequest()
|
let fetchRequest = Cheat.fetchRequest()
|
||||||
fetchRequest.returnsObjectsAsFaults = false
|
fetchRequest.returnsObjectsAsFaults = false
|
||||||
fetchRequest.predicate = NSPredicate(format: "%K == %@", Cheat.Attributes.game.rawValue, game)
|
fetchRequest.predicate = Predicate(format: "%K == %@", Cheat.Attributes.game.rawValue, game)
|
||||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: Cheat.Attributes.name.rawValue, ascending: true)]
|
fetchRequest.sortDescriptors = [SortDescriptor(key: Cheat.Attributes.name.rawValue, ascending: true)]
|
||||||
|
|
||||||
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
|
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
|
||||||
self.fetchedResultsController.delegate = self
|
self.fetchedResultsController.delegate = self
|
||||||
@ -98,13 +98,13 @@ private extension CheatsViewController
|
|||||||
{
|
{
|
||||||
if let fetchedObjects = self.fetchedResultsController.fetchedObjects where fetchedObjects.count > 0
|
if let fetchedObjects = self.fetchedResultsController.fetchedObjects where fetchedObjects.count > 0
|
||||||
{
|
{
|
||||||
self.tableView.separatorStyle = .SingleLine
|
self.tableView.separatorStyle = .singleLine
|
||||||
self.backgroundView.hidden = true
|
self.backgroundView.isHidden = true
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self.tableView.separatorStyle = .None
|
self.tableView.separatorStyle = .none
|
||||||
self.backgroundView.hidden = false
|
self.backgroundView.isHidden = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,14 +119,14 @@ private extension CheatsViewController
|
|||||||
editCheatViewController.presentWithPresentingViewController(self)
|
editCheatViewController.presentWithPresentingViewController(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteCheat(cheat: Cheat)
|
func deleteCheat(_ cheat: Cheat)
|
||||||
{
|
{
|
||||||
self.delegate.cheatsViewController(self, didDeactivateCheat: cheat)
|
self.delegate.cheatsViewController(self, didDeactivateCheat: cheat)
|
||||||
|
|
||||||
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
backgroundContext.performBlock {
|
backgroundContext.perform {
|
||||||
let temporaryCheat = backgroundContext.objectWithID(cheat.objectID)
|
let temporaryCheat = backgroundContext.object(with: cheat.objectID)
|
||||||
backgroundContext.deleteObject(temporaryCheat)
|
backgroundContext.delete(temporaryCheat)
|
||||||
backgroundContext.saveWithErrorLogging()
|
backgroundContext.saveWithErrorLogging()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,17 +136,17 @@ private extension CheatsViewController
|
|||||||
/// Convenience
|
/// Convenience
|
||||||
private extension CheatsViewController
|
private extension CheatsViewController
|
||||||
{
|
{
|
||||||
func configure(cell cell: UITableViewCell, forIndexPath indexPath: NSIndexPath)
|
func configure(cell: UITableViewCell, forIndexPath indexPath: IndexPath)
|
||||||
{
|
{
|
||||||
let cheat = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Cheat
|
let cheat = self.fetchedResultsController.object(at: indexPath) as! Cheat
|
||||||
cell.textLabel?.text = cheat.name
|
cell.textLabel?.text = cheat.name
|
||||||
cell.textLabel?.font = UIFont.boldSystemFontOfSize(cell.textLabel!.font.pointSize)
|
cell.textLabel?.font = UIFont.boldSystemFont(ofSize: cell.textLabel!.font.pointSize)
|
||||||
cell.accessoryType = cheat.enabled ? .Checkmark : .None
|
cell.accessoryType = cheat.enabled ? .checkmark : .none
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeEditCheatViewController(cheat cheat: Cheat?) -> EditCheatViewController
|
func makeEditCheatViewController(cheat: Cheat?) -> EditCheatViewController
|
||||||
{
|
{
|
||||||
let editCheatViewController = self.storyboard!.instantiateViewControllerWithIdentifier("editCheatViewController") as! EditCheatViewController
|
let editCheatViewController = self.storyboard!.instantiateViewController(withIdentifier: "editCheatViewController") as! EditCheatViewController
|
||||||
editCheatViewController.delegate = self
|
editCheatViewController.delegate = self
|
||||||
editCheatViewController.supportedCheatFormats = self.delegate.cheatsViewControllerActiveEmulatorCore(self).supportedCheatFormats
|
editCheatViewController.supportedCheatFormats = self.delegate.cheatsViewControllerActiveEmulatorCore(self).supportedCheatFormats
|
||||||
editCheatViewController.cheat = cheat
|
editCheatViewController.cheat = cheat
|
||||||
@ -160,21 +160,21 @@ extension CheatsViewController
|
|||||||
{
|
{
|
||||||
// MARK: - Table view data source
|
// MARK: - Table view data source
|
||||||
|
|
||||||
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
|
override func numberOfSections(in tableView: UITableView) -> Int
|
||||||
{
|
{
|
||||||
let numberOfSections = self.fetchedResultsController.sections!.count
|
let numberOfSections = self.fetchedResultsController.sections!.count
|
||||||
return numberOfSections
|
return numberOfSections
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
|
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
|
||||||
{
|
{
|
||||||
let section = self.fetchedResultsController.sections![section]
|
let section = self.fetchedResultsController.sections![section]
|
||||||
return section.numberOfObjects
|
return section.numberOfObjects
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
||||||
{
|
{
|
||||||
let cell = tableView.dequeueReusableCellWithIdentifier(RSTGenericCellIdentifier, forIndexPath: indexPath)
|
let cell = tableView.dequeueReusableCell(withIdentifier: RSTGenericCellIdentifier, for: indexPath)
|
||||||
self.configure(cell: cell, forIndexPath: indexPath)
|
self.configure(cell: cell, forIndexPath: indexPath)
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
@ -182,13 +182,13 @@ extension CheatsViewController
|
|||||||
|
|
||||||
extension CheatsViewController
|
extension CheatsViewController
|
||||||
{
|
{
|
||||||
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
|
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
|
||||||
{
|
{
|
||||||
let cheat = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Cheat
|
let cheat = self.fetchedResultsController.object(at: indexPath) as! Cheat
|
||||||
|
|
||||||
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
backgroundContext.performBlockAndWait {
|
backgroundContext.performAndWait {
|
||||||
let temporaryCheat = backgroundContext.objectWithID(cheat.objectID) as! Cheat
|
let temporaryCheat = backgroundContext.object(with: cheat.objectID) as! Cheat
|
||||||
temporaryCheat.enabled = !temporaryCheat.enabled
|
temporaryCheat.enabled = !temporaryCheat.enabled
|
||||||
|
|
||||||
if temporaryCheat.enabled
|
if temporaryCheat.enabled
|
||||||
@ -215,18 +215,18 @@ extension CheatsViewController
|
|||||||
backgroundContext.saveWithErrorLogging()
|
backgroundContext.saveWithErrorLogging()
|
||||||
}
|
}
|
||||||
|
|
||||||
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
|
self.tableView.reloadRows(at: [indexPath], with: .none)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]?
|
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
|
||||||
{
|
{
|
||||||
let cheat = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Cheat
|
let cheat = self.fetchedResultsController.object(at: indexPath) as! Cheat
|
||||||
|
|
||||||
let deleteAction = UITableViewRowAction(style: .Destructive, title: NSLocalizedString("Delete", comment: "")) { (action, indexPath) in
|
let deleteAction = UITableViewRowAction(style: UITableViewRowActionStyle(), title: NSLocalizedString("Delete", comment: "")) { (action, indexPath) in
|
||||||
self.deleteCheat(cheat)
|
self.deleteCheat(cheat)
|
||||||
}
|
}
|
||||||
|
|
||||||
let editAction = UITableViewRowAction(style: .Normal, title: NSLocalizedString("Edit", comment: "")) { (action, indexPath) in
|
let editAction = UITableViewRowAction(style: .normal, title: NSLocalizedString("Edit", comment: "")) { (action, indexPath) in
|
||||||
let editCheatViewController = self.makeEditCheatViewController(cheat: cheat)
|
let editCheatViewController = self.makeEditCheatViewController(cheat: cheat)
|
||||||
editCheatViewController.presentWithPresentingViewController(self)
|
editCheatViewController.presentWithPresentingViewController(self)
|
||||||
}
|
}
|
||||||
@ -234,7 +234,7 @@ extension CheatsViewController
|
|||||||
return [deleteAction, editAction]
|
return [deleteAction, editAction]
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
|
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
|
||||||
{
|
{
|
||||||
// This method intentionally left blank because someone decided it was a Good Idea™ to require this method be implemented to use UITableViewRowActions
|
// This method intentionally left blank because someone decided it was a Good Idea™ to require this method be implemented to use UITableViewRowActions
|
||||||
}
|
}
|
||||||
@ -243,20 +243,20 @@ extension CheatsViewController
|
|||||||
//MARK: - <UIViewControllerPreviewingDelegate> -
|
//MARK: - <UIViewControllerPreviewingDelegate> -
|
||||||
extension CheatsViewController: UIViewControllerPreviewingDelegate
|
extension CheatsViewController: UIViewControllerPreviewingDelegate
|
||||||
{
|
{
|
||||||
func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?
|
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?
|
||||||
{
|
{
|
||||||
guard let indexPath = self.tableView.indexPathForRowAtPoint(location) else { return nil }
|
guard let indexPath = self.tableView.indexPathForRow(at: location) else { return nil }
|
||||||
|
|
||||||
let frame = self.tableView.rectForRowAtIndexPath(indexPath)
|
let frame = self.tableView.rectForRow(at: indexPath)
|
||||||
previewingContext.sourceRect = frame
|
previewingContext.sourceRect = frame
|
||||||
|
|
||||||
let cheat = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Cheat
|
let cheat = self.fetchedResultsController.object(at: indexPath) as! Cheat
|
||||||
|
|
||||||
let editCheatViewController = self.makeEditCheatViewController(cheat: cheat)
|
let editCheatViewController = self.makeEditCheatViewController(cheat: cheat)
|
||||||
return editCheatViewController
|
return editCheatViewController
|
||||||
}
|
}
|
||||||
|
|
||||||
func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController)
|
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController)
|
||||||
{
|
{
|
||||||
let editCheatViewController = viewControllerToCommit as! EditCheatViewController
|
let editCheatViewController = viewControllerToCommit as! EditCheatViewController
|
||||||
editCheatViewController.presentWithPresentingViewController(self)
|
editCheatViewController.presentWithPresentingViewController(self)
|
||||||
@ -266,7 +266,7 @@ extension CheatsViewController: UIViewControllerPreviewingDelegate
|
|||||||
//MARK: - <EditCheatViewControllerDelegate> -
|
//MARK: - <EditCheatViewControllerDelegate> -
|
||||||
extension CheatsViewController: EditCheatViewControllerDelegate
|
extension CheatsViewController: EditCheatViewControllerDelegate
|
||||||
{
|
{
|
||||||
func editCheatViewController(editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?) throws
|
func editCheatViewController(_ editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?) throws
|
||||||
{
|
{
|
||||||
try self.delegate.cheatsViewController(self, didActivateCheat: cheat)
|
try self.delegate.cheatsViewController(self, didActivateCheat: cheat)
|
||||||
|
|
||||||
@ -274,7 +274,7 @@ extension CheatsViewController: EditCheatViewControllerDelegate
|
|||||||
{
|
{
|
||||||
let code = cheat.code
|
let code = cheat.code
|
||||||
|
|
||||||
previousCheat.managedObjectContext?.performBlockAndWait({
|
previousCheat.managedObjectContext?.performAndWait({
|
||||||
|
|
||||||
guard previousCheat.code != code else { return }
|
guard previousCheat.code != code else { return }
|
||||||
|
|
||||||
@ -283,7 +283,7 @@ extension CheatsViewController: EditCheatViewControllerDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func editCheatViewController(editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat)
|
func editCheatViewController(_ editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat)
|
||||||
{
|
{
|
||||||
self.delegate.cheatsViewController(self, didDeactivateCheat: cheat)
|
self.delegate.cheatsViewController(self, didDeactivateCheat: cheat)
|
||||||
}
|
}
|
||||||
@ -292,7 +292,7 @@ extension CheatsViewController: EditCheatViewControllerDelegate
|
|||||||
//MARK: - <NSFetchedResultsControllerDelegate> -
|
//MARK: - <NSFetchedResultsControllerDelegate> -
|
||||||
extension CheatsViewController: NSFetchedResultsControllerDelegate
|
extension CheatsViewController: NSFetchedResultsControllerDelegate
|
||||||
{
|
{
|
||||||
func controllerDidChangeContent(controller: NSFetchedResultsController)
|
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
|
||||||
{
|
{
|
||||||
self.tableView.reloadData()
|
self.tableView.reloadData()
|
||||||
self.updateBackgroundView()
|
self.updateBackgroundView()
|
||||||
|
|||||||
@ -14,13 +14,13 @@ import Roxas
|
|||||||
|
|
||||||
protocol EditCheatViewControllerDelegate: class
|
protocol EditCheatViewControllerDelegate: class
|
||||||
{
|
{
|
||||||
func editCheatViewController(editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?) throws
|
func editCheatViewController(_ editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?) throws
|
||||||
func editCheatViewController(editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat)
|
func editCheatViewController(_ editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat)
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension EditCheatViewController
|
private extension EditCheatViewController
|
||||||
{
|
{
|
||||||
enum ValidationError: ErrorType
|
enum ValidationError: ErrorProtocol
|
||||||
{
|
{
|
||||||
case invalidCode
|
case invalidCode
|
||||||
case duplicateName
|
case duplicateName
|
||||||
@ -66,18 +66,18 @@ extension EditCheatViewController
|
|||||||
var type: CheatType!
|
var type: CheatType!
|
||||||
var code: String!
|
var code: String!
|
||||||
|
|
||||||
self.managedObjectContext.performBlockAndWait {
|
self.managedObjectContext.performAndWait {
|
||||||
|
|
||||||
// Main Thread context is read-only, so we either create a new cheat, or get a reference to the current cheat in a new background context
|
// Main Thread context is read-only, so we either create a new cheat, or get a reference to the current cheat in a new background context
|
||||||
|
|
||||||
if let cheat = self.cheat
|
if let cheat = self.cheat
|
||||||
{
|
{
|
||||||
self.mutableCheat = self.managedObjectContext.objectWithID(cheat.objectID) as? Cheat
|
self.mutableCheat = self.managedObjectContext.object(with: cheat.objectID) as? Cheat
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self.mutableCheat = Cheat.insertIntoManagedObjectContext(self.managedObjectContext)
|
self.mutableCheat = Cheat.insertIntoManagedObjectContext(self.managedObjectContext)
|
||||||
self.mutableCheat.game = self.managedObjectContext.objectWithID(self.game.objectID) as! Game
|
self.mutableCheat.game = self.managedObjectContext.object(with: self.game.objectID) as! Game
|
||||||
self.mutableCheat.type = self.supportedCheatFormats.first!.type
|
self.mutableCheat.type = self.supportedCheatFormats.first!.type
|
||||||
self.mutableCheat.code = ""
|
self.mutableCheat.code = ""
|
||||||
self.mutableCheat.name = ""
|
self.mutableCheat.name = ""
|
||||||
@ -107,12 +107,12 @@ extension EditCheatViewController
|
|||||||
|
|
||||||
self.typeSegmentedControl.removeAllSegments()
|
self.typeSegmentedControl.removeAllSegments()
|
||||||
|
|
||||||
for (index, format) in self.supportedCheatFormats.enumerate()
|
for (index, format) in self.supportedCheatFormats.enumerated()
|
||||||
{
|
{
|
||||||
self.typeSegmentedControl.insertSegmentWithTitle(format.name, atIndex: index, animated: false)
|
self.typeSegmentedControl.insertSegment(withTitle: format.name, at: index, animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let index = self.supportedCheatFormats.indexOf({ $0.type == type })
|
if let index = self.supportedCheatFormats.index(where: { $0.type == type })
|
||||||
{
|
{
|
||||||
self.typeSegmentedControl.selectedSegmentIndex = index
|
self.typeSegmentedControl.selectedSegmentIndex = index
|
||||||
}
|
}
|
||||||
@ -125,13 +125,13 @@ extension EditCheatViewController
|
|||||||
self.updateSaveButtonState()
|
self.updateSaveButtonState()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidAppear(animated: Bool)
|
override func viewDidAppear(_ animated: Bool)
|
||||||
{
|
{
|
||||||
super.viewDidAppear(animated)
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
// This matters when going from peek -> pop
|
// This matters when going from peek -> pop
|
||||||
// Otherwise, has no effect because viewDidLayoutSubviews has already been called
|
// Otherwise, has no effect because viewDidLayoutSubviews has already been called
|
||||||
if self.appearing && !self.isPreviewing
|
if self.isAppearing && !self.isPreviewing
|
||||||
{
|
{
|
||||||
self.nameTextField.becomeFirstResponder()
|
self.nameTextField.becomeFirstResponder()
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ extension EditCheatViewController
|
|||||||
self.codeTextView.textContainer.lineFragmentPadding = 0
|
self.codeTextView.textContainer.lineFragmentPadding = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.appearing && !self.isPreviewing
|
if self.isAppearing && !self.isPreviewing
|
||||||
{
|
{
|
||||||
self.nameTextField.becomeFirstResponder()
|
self.nameTextField.becomeFirstResponder()
|
||||||
}
|
}
|
||||||
@ -159,35 +159,35 @@ extension EditCheatViewController
|
|||||||
{
|
{
|
||||||
guard let cheat = self.cheat else { return [] }
|
guard let cheat = self.cheat else { return [] }
|
||||||
|
|
||||||
let copyCodeAction = UIPreviewAction(title: NSLocalizedString("Copy Code", comment: ""), style: .Default) { (action, viewController) in
|
let copyCodeAction = UIPreviewAction(title: NSLocalizedString("Copy Code", comment: ""), style: .default) { (action, viewController) in
|
||||||
UIPasteboard.generalPasteboard().string = cheat.code
|
UIPasteboard.general().string = cheat.code
|
||||||
}
|
}
|
||||||
|
|
||||||
let presentingViewController = self.presentingViewController!
|
let presentingViewController = self.presentingViewController!
|
||||||
|
|
||||||
let editCheatAction = UIPreviewAction(title: NSLocalizedString("Edit", comment: ""), style: .Default) { (action, viewController) in
|
let editCheatAction = UIPreviewAction(title: NSLocalizedString("Edit", comment: ""), style: .default) { (action, viewController) in
|
||||||
// Delaying until next run loop prevents self from being dismissed immediately
|
// Delaying until next run loop prevents self from being dismissed immediately
|
||||||
dispatch_async(dispatch_get_main_queue()) {
|
DispatchQueue.main.async {
|
||||||
let editCheatViewController = viewController as! EditCheatViewController
|
let editCheatViewController = viewController as! EditCheatViewController
|
||||||
editCheatViewController.presentWithPresentingViewController(presentingViewController)
|
editCheatViewController.presentWithPresentingViewController(presentingViewController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let deleteAction = UIPreviewAction(title: NSLocalizedString("Delete", comment: ""), style: .Destructive) { [unowned self] (action, viewController) in
|
let deleteAction = UIPreviewAction(title: NSLocalizedString("Delete", comment: ""), style: .destructive) { [unowned self] (action, viewController) in
|
||||||
self.delegate?.editCheatViewController(self, deactivateCheat: cheat)
|
self.delegate?.editCheatViewController(self, deactivateCheat: cheat)
|
||||||
|
|
||||||
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
backgroundContext.performBlock {
|
backgroundContext.perform {
|
||||||
let temporaryCheat = backgroundContext.objectWithID(cheat.objectID)
|
let temporaryCheat = backgroundContext.object(with: cheat.objectID)
|
||||||
backgroundContext.deleteObject(temporaryCheat)
|
backgroundContext.delete(temporaryCheat)
|
||||||
backgroundContext.saveWithErrorLogging()
|
backgroundContext.saveWithErrorLogging()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let cancelDeleteAction = UIPreviewAction(title: NSLocalizedString("Cancel", comment: ""), style: .Default) { (action, viewController) in
|
let cancelDeleteAction = UIPreviewAction(title: NSLocalizedString("Cancel", comment: ""), style: .default) { (action, viewController) in
|
||||||
}
|
}
|
||||||
|
|
||||||
let deleteActionGroup = UIPreviewActionGroup(title: NSLocalizedString("Delete", comment: ""), style: .Destructive, actions: [deleteAction, cancelDeleteAction])
|
let deleteActionGroup = UIPreviewActionGroup(title: NSLocalizedString("Delete", comment: ""), style: .destructive, actions: [deleteAction, cancelDeleteAction])
|
||||||
|
|
||||||
return [copyCodeAction, editCheatAction, deleteActionGroup]
|
return [copyCodeAction, editCheatAction, deleteActionGroup]
|
||||||
}
|
}
|
||||||
@ -198,7 +198,7 @@ extension EditCheatViewController
|
|||||||
// Dispose of any resources that can be recreated.
|
// Dispose of any resources that can be recreated.
|
||||||
}
|
}
|
||||||
|
|
||||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
|
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
|
||||||
{
|
{
|
||||||
self.nameTextField.resignFirstResponder()
|
self.nameTextField.resignFirstResponder()
|
||||||
self.codeTextView.resignFirstResponder()
|
self.codeTextView.resignFirstResponder()
|
||||||
@ -207,19 +207,19 @@ extension EditCheatViewController
|
|||||||
|
|
||||||
internal extension EditCheatViewController
|
internal extension EditCheatViewController
|
||||||
{
|
{
|
||||||
func presentWithPresentingViewController(presentingViewController: UIViewController)
|
func presentWithPresentingViewController(_ presentingViewController: UIViewController)
|
||||||
{
|
{
|
||||||
let navigationController = RSTNavigationController(rootViewController: self)
|
let navigationController = RSTNavigationController(rootViewController: self)
|
||||||
navigationController.modalPresentationStyle = .OverFullScreen // Keeps PausePresentationController active to ensure layout is not messed up
|
navigationController.modalPresentationStyle = .overFullScreen // Keeps PausePresentationController active to ensure layout is not messed up
|
||||||
navigationController.modalPresentationCapturesStatusBarAppearance = true
|
navigationController.modalPresentationCapturesStatusBarAppearance = true
|
||||||
|
|
||||||
presentingViewController.presentViewController(navigationController, animated: true, completion: nil)
|
presentingViewController.present(navigationController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension EditCheatViewController
|
private extension EditCheatViewController
|
||||||
{
|
{
|
||||||
@IBAction func updateCheatName(sender: UITextField)
|
@IBAction func updateCheatName(_ sender: UITextField)
|
||||||
{
|
{
|
||||||
var title = sender.text ?? ""
|
var title = sender.text ?? ""
|
||||||
if title.characters.count == 0
|
if title.characters.count == 0
|
||||||
@ -232,17 +232,17 @@ private extension EditCheatViewController
|
|||||||
self.updateSaveButtonState()
|
self.updateSaveButtonState()
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func updateCheatType(sender: UISegmentedControl)
|
@IBAction func updateCheatType(_ sender: UISegmentedControl)
|
||||||
{
|
{
|
||||||
self.codeTextView.cheatFormat = self.selectedCheatFormat
|
self.codeTextView.cheatFormat = self.selectedCheatFormat
|
||||||
|
|
||||||
UIView.performWithoutAnimation {
|
UIView.performWithoutAnimation {
|
||||||
self.tableView.reloadSections(NSIndexSet(index: Section.type.rawValue), withRowAnimation: .None)
|
self.tableView.reloadSections(IndexSet(integer: Section.type.rawValue), with: .none)
|
||||||
|
|
||||||
// Hacky-ish workaround so we can update the footer text for the code section without causing text view to resign first responder status
|
// Hacky-ish workaround so we can update the footer text for the code section without causing text view to resign first responder status
|
||||||
self.tableView.beginUpdates()
|
self.tableView.beginUpdates()
|
||||||
|
|
||||||
if let footerView = self.tableView.footerViewForSection(Section.code.rawValue)
|
if let footerView = self.tableView.footerView(forSection: Section.code.rawValue)
|
||||||
{
|
{
|
||||||
footerView.textLabel!.text = self.tableView(self.tableView, titleForFooterInSection: Section.code.rawValue)
|
footerView.textLabel!.text = self.tableView(self.tableView, titleForFooterInSection: Section.code.rawValue)
|
||||||
footerView.sizeToFit()
|
footerView.sizeToFit()
|
||||||
@ -257,12 +257,12 @@ private extension EditCheatViewController
|
|||||||
let isValidName = !(self.nameTextField.text ?? "").isEmpty
|
let isValidName = !(self.nameTextField.text ?? "").isEmpty
|
||||||
let isValidCode = !self.codeTextView.text.isEmpty
|
let isValidCode = !self.codeTextView.text.isEmpty
|
||||||
|
|
||||||
self.navigationItem.rightBarButtonItem?.enabled = isValidName && isValidCode
|
self.navigationItem.rightBarButtonItem?.isEnabled = isValidName && isValidCode
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func saveCheat(sender: UIBarButtonItem)
|
@IBAction func saveCheat(_ sender: UIBarButtonItem)
|
||||||
{
|
{
|
||||||
self.mutableCheat.managedObjectContext?.performBlockAndWait {
|
self.mutableCheat.managedObjectContext?.performAndWait {
|
||||||
|
|
||||||
self.mutableCheat.name = self.nameTextField.text ?? ""
|
self.mutableCheat.name = self.nameTextField.text ?? ""
|
||||||
self.mutableCheat.type = self.selectedCheatFormat.type
|
self.mutableCheat.type = self.selectedCheatFormat.type
|
||||||
@ -272,7 +272,7 @@ private extension EditCheatViewController
|
|||||||
{
|
{
|
||||||
try self.validateCheat(self.mutableCheat)
|
try self.validateCheat(self.mutableCheat)
|
||||||
self.mutableCheat.managedObjectContext?.saveWithErrorLogging()
|
self.mutableCheat.managedObjectContext?.saveWithErrorLogging()
|
||||||
self.performSegueWithIdentifier("unwindEditCheatSegue", sender: sender)
|
self.performSegue(withIdentifier: "unwindEditCheatSegue", sender: sender)
|
||||||
}
|
}
|
||||||
catch ValidationError.invalidCode
|
catch ValidationError.invalidCode
|
||||||
{
|
{
|
||||||
@ -299,13 +299,13 @@ private extension EditCheatViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateCheat(cheat: Cheat) throws
|
func validateCheat(_ cheat: Cheat) throws
|
||||||
{
|
{
|
||||||
let name = cheat.name!
|
let name = cheat.name!
|
||||||
let code = cheat.code
|
let code = cheat.code
|
||||||
|
|
||||||
// Find all cheats that are for the same game, don't have the same identifier as the current cheat, but have either the same name or code
|
// Find all cheats that are for the same game, don't have the same identifier as the current cheat, but have either the same name or code
|
||||||
let predicate = NSPredicate(format: "%K == %@ AND %K != %@ AND (%K == %@ OR %K == %@)", Cheat.Attributes.game.rawValue, cheat.game, Cheat.Attributes.identifier.rawValue, cheat.identifier, Cheat.Attributes.code.rawValue, code, Cheat.Attributes.name.rawValue, name)
|
let predicate = Predicate(format: "%K == %@ AND %K != %@ AND (%K == %@ OR %K == %@)", Cheat.Attributes.game.rawValue, cheat.game, Cheat.Attributes.identifier.rawValue, cheat.identifier, Cheat.Attributes.code.rawValue, code, Cheat.Attributes.name.rawValue, name)
|
||||||
|
|
||||||
let cheats = Cheat.instancesWithPredicate(predicate, inManagedObjectContext: self.managedObjectContext, type: Cheat.self)
|
let cheats = Cheat.instancesWithPredicate(predicate, inManagedObjectContext: self.managedObjectContext, type: Cheat.self)
|
||||||
for cheat in cheats
|
for cheat in cheats
|
||||||
@ -330,26 +330,26 @@ private extension EditCheatViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func textFieldDidEndEditing(sender: UITextField)
|
@IBAction func textFieldDidEndEditing(_ sender: UITextField)
|
||||||
{
|
{
|
||||||
sender.resignFirstResponder()
|
sender.resignFirstResponder()
|
||||||
}
|
}
|
||||||
|
|
||||||
func presentErrorAlert(title title: String, message: String, handler: (Void -> Void)?)
|
func presentErrorAlert(title: String, message: String, handler: ((Void) -> Void)?)
|
||||||
{
|
{
|
||||||
dispatch_async(dispatch_get_main_queue()) {
|
DispatchQueue.main.async {
|
||||||
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
|
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .Default, handler: { action in
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: { action in
|
||||||
handler?()
|
handler?()
|
||||||
}))
|
}))
|
||||||
self.presentViewController(alertController, animated: true, completion: nil)
|
self.present(alertController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension EditCheatViewController
|
extension EditCheatViewController
|
||||||
{
|
{
|
||||||
override func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String?
|
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String?
|
||||||
{
|
{
|
||||||
switch Section(rawValue: section)!
|
switch Section(rawValue: section)!
|
||||||
{
|
{
|
||||||
@ -360,8 +360,8 @@ extension EditCheatViewController
|
|||||||
return title
|
return title
|
||||||
|
|
||||||
case .code:
|
case .code:
|
||||||
let containsSpaces = self.selectedCheatFormat.format.containsString(" ")
|
let containsSpaces = self.selectedCheatFormat.format.contains(" ")
|
||||||
let containsDashes = self.selectedCheatFormat.format.containsString("-")
|
let containsDashes = self.selectedCheatFormat.format.contains("-")
|
||||||
|
|
||||||
switch (containsSpaces, containsDashes)
|
switch (containsSpaces, containsDashes)
|
||||||
{
|
{
|
||||||
@ -376,7 +376,7 @@ extension EditCheatViewController
|
|||||||
|
|
||||||
extension EditCheatViewController: UITextViewDelegate
|
extension EditCheatViewController: UITextViewDelegate
|
||||||
{
|
{
|
||||||
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool
|
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool
|
||||||
{
|
{
|
||||||
defer { self.updateSaveButtonState() }
|
defer { self.updateSaveButtonState() }
|
||||||
|
|
||||||
@ -392,8 +392,8 @@ extension EditCheatViewController: UITextViewDelegate
|
|||||||
|
|
||||||
// We need to manually add back the attributes when manually modifying the underlying text storage
|
// We need to manually add back the attributes when manually modifying the underlying text storage
|
||||||
// Otherwise, pasting text into an empty text view will result in the wrong font being used
|
// Otherwise, pasting text into an empty text view will result in the wrong font being used
|
||||||
let attributedString = NSAttributedString(string: sanitizedText, attributes: textView.typingAttributes)
|
let attributedString = AttributedString(string: sanitizedText, attributes: textView.typingAttributes)
|
||||||
textView.textStorage.replaceCharactersInRange(range, withAttributedString: attributedString)
|
textView.textStorage.replaceCharacters(in: range, with: attributedString)
|
||||||
|
|
||||||
// We must add attributedString.length, not range.length, in case the attributed string's length differs
|
// We must add attributedString.length, not range.length, in case the attributed string's length differs
|
||||||
textView.selectedRange = NSRange(location: range.location + attributedString.length, length: 0)
|
textView.selectedRange = NSRange(location: range.location + attributedString.length, length: 0)
|
||||||
|
|||||||
@ -12,11 +12,11 @@ struct PauseItem: Equatable
|
|||||||
{
|
{
|
||||||
let image: UIImage
|
let image: UIImage
|
||||||
let text: String
|
let text: String
|
||||||
let action: (PauseItem -> Void)
|
let action: ((PauseItem) -> Void)
|
||||||
|
|
||||||
var selected = false
|
var selected = false
|
||||||
|
|
||||||
init(image: UIImage, text: String, action: (PauseItem -> Void))
|
init(image: UIImage, text: String, action: ((PauseItem) -> Void))
|
||||||
{
|
{
|
||||||
self.image = image
|
self.image = image
|
||||||
self.text = text
|
self.text = text
|
||||||
|
|||||||
@ -27,11 +27,11 @@ class PauseMenuViewController: UICollectionViewController
|
|||||||
|
|
||||||
override var preferredContentSize: CGSize {
|
override var preferredContentSize: CGSize {
|
||||||
set { }
|
set { }
|
||||||
get { return self.collectionView?.contentSize ?? CGSizeZero }
|
get { return self.collectionView?.contentSize ?? CGSize.zero }
|
||||||
}
|
}
|
||||||
|
|
||||||
private var prototypeCell = GridCollectionViewCell()
|
private var prototypeCell = GridCollectionViewCell()
|
||||||
private var previousIndexPath: NSIndexPath? = nil
|
private var previousIndexPath: IndexPath? = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
extension PauseMenuViewController
|
extension PauseMenuViewController
|
||||||
@ -45,16 +45,16 @@ extension PauseMenuViewController
|
|||||||
collectionViewLayout.usesEqualHorizontalSpacingDistributionForSingleRow = true
|
collectionViewLayout.usesEqualHorizontalSpacingDistributionForSingleRow = true
|
||||||
|
|
||||||
// Manually update prototype cell properties
|
// Manually update prototype cell properties
|
||||||
self.prototypeCell.contentView.widthAnchor.constraintEqualToConstant(collectionViewLayout.itemWidth).active = true
|
self.prototypeCell.contentView.widthAnchor.constraint(equalToConstant: collectionViewLayout.itemWidth).isActive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidAppear(animated: Bool)
|
override func viewDidAppear(_ animated: Bool)
|
||||||
{
|
{
|
||||||
super.viewDidAppear(animated)
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
if let indexPath = self.previousIndexPath
|
if let indexPath = self.previousIndexPath
|
||||||
{
|
{
|
||||||
UIView.animateWithDuration(0.2) {
|
UIView.animate(withDuration: 0.2) {
|
||||||
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
|
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,54 +63,54 @@ extension PauseMenuViewController
|
|||||||
|
|
||||||
private extension PauseMenuViewController
|
private extension PauseMenuViewController
|
||||||
{
|
{
|
||||||
func configureCollectionViewCell(cell: GridCollectionViewCell, forIndexPath indexPath: NSIndexPath)
|
func configureCollectionViewCell(_ cell: GridCollectionViewCell, forIndexPath indexPath: IndexPath)
|
||||||
{
|
{
|
||||||
let pauseItem = self.items[indexPath.item]
|
let pauseItem = self.items[(indexPath as NSIndexPath).item]
|
||||||
|
|
||||||
cell.maximumImageSize = CGSize(width: 60, height: 60)
|
cell.maximumImageSize = CGSize(width: 60, height: 60)
|
||||||
|
|
||||||
cell.imageView.image = pauseItem.image
|
cell.imageView.image = pauseItem.image
|
||||||
cell.imageView.contentMode = .Center
|
cell.imageView.contentMode = .center
|
||||||
cell.imageView.layer.borderWidth = 2
|
cell.imageView.layer.borderWidth = 2
|
||||||
cell.imageView.layer.borderColor = UIColor.whiteColor().CGColor
|
cell.imageView.layer.borderColor = UIColor.white().cgColor
|
||||||
cell.imageView.layer.cornerRadius = 10
|
cell.imageView.layer.cornerRadius = 10
|
||||||
|
|
||||||
cell.textLabel.text = pauseItem.text
|
cell.textLabel.text = pauseItem.text
|
||||||
cell.textLabel.textColor = UIColor.whiteColor()
|
cell.textLabel.textColor = UIColor.white()
|
||||||
|
|
||||||
if pauseItem.selected
|
if pauseItem.selected
|
||||||
{
|
{
|
||||||
cell.imageView.tintColor = UIColor.blackColor()
|
cell.imageView.tintColor = UIColor.black()
|
||||||
cell.imageView.backgroundColor = UIColor.whiteColor()
|
cell.imageView.backgroundColor = UIColor.white()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cell.imageView.tintColor = UIColor.whiteColor()
|
cell.imageView.tintColor = UIColor.white()
|
||||||
cell.imageView.backgroundColor = UIColor.clearColor()
|
cell.imageView.backgroundColor = UIColor.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toggleSelectedStateForPauseItemAtIndexPath(indexPath: NSIndexPath)
|
func toggleSelectedStateForPauseItemAtIndexPath(_ indexPath: IndexPath)
|
||||||
{
|
{
|
||||||
var pauseItem = self.items[indexPath.item]
|
var pauseItem = self.items[(indexPath as NSIndexPath).item]
|
||||||
pauseItem.selected = !pauseItem.selected
|
pauseItem.selected = !pauseItem.selected
|
||||||
self.items[indexPath.item] = pauseItem
|
self.items[(indexPath as NSIndexPath).item] = pauseItem
|
||||||
|
|
||||||
let cell = self.collectionView!.cellForItemAtIndexPath(indexPath) as! GridCollectionViewCell
|
let cell = self.collectionView!.cellForItem(at: indexPath) as! GridCollectionViewCell
|
||||||
self.configureCollectionViewCell(cell, forIndexPath: indexPath)
|
self.configureCollectionViewCell(cell, forIndexPath: indexPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension PauseMenuViewController
|
extension PauseMenuViewController
|
||||||
{
|
{
|
||||||
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
|
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
|
||||||
{
|
{
|
||||||
return self.items.count
|
return self.items.count
|
||||||
}
|
}
|
||||||
|
|
||||||
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
|
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
|
||||||
{
|
{
|
||||||
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(RSTGenericCellIdentifier, forIndexPath: indexPath) as! GridCollectionViewCell
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: RSTGenericCellIdentifier, for: indexPath) as! GridCollectionViewCell
|
||||||
self.configureCollectionViewCell(cell, forIndexPath: indexPath)
|
self.configureCollectionViewCell(cell, forIndexPath: indexPath)
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
@ -118,34 +118,34 @@ extension PauseMenuViewController
|
|||||||
|
|
||||||
extension PauseMenuViewController: UICollectionViewDelegateFlowLayout
|
extension PauseMenuViewController: UICollectionViewDelegateFlowLayout
|
||||||
{
|
{
|
||||||
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
|
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
|
||||||
{
|
{
|
||||||
self.configureCollectionViewCell(self.prototypeCell, forIndexPath: indexPath)
|
self.configureCollectionViewCell(self.prototypeCell, forIndexPath: indexPath)
|
||||||
|
|
||||||
let size = self.prototypeCell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
|
let size = self.prototypeCell.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension PauseMenuViewController
|
extension PauseMenuViewController
|
||||||
{
|
{
|
||||||
override func collectionView(collectionView: UICollectionView, didHighlightItemAtIndexPath indexPath: NSIndexPath)
|
override func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath)
|
||||||
{
|
{
|
||||||
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
|
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func collectionView(collectionView: UICollectionView, didUnhighlightItemAtIndexPath indexPath: NSIndexPath)
|
override func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath)
|
||||||
{
|
{
|
||||||
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
|
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
|
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
|
||||||
{
|
{
|
||||||
self.previousIndexPath = indexPath
|
self.previousIndexPath = indexPath
|
||||||
|
|
||||||
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
|
self.toggleSelectedStateForPauseItemAtIndexPath(indexPath)
|
||||||
|
|
||||||
let pauseItem = self.items[indexPath.item]
|
let pauseItem = self.items[(indexPath as NSIndexPath).item]
|
||||||
pauseItem.action(pauseItem)
|
pauseItem.action(pauseItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ class PauseViewController: UIViewController, PauseInfoProvidable
|
|||||||
var pauseText: String? = nil
|
var pauseText: String? = nil
|
||||||
|
|
||||||
private weak var saveStatesViewControllerDelegate: SaveStatesViewControllerDelegate?
|
private weak var saveStatesViewControllerDelegate: SaveStatesViewControllerDelegate?
|
||||||
private var saveStatesViewControllerMode = SaveStatesViewController.Mode.Saving
|
private var saveStatesViewControllerMode = SaveStatesViewController.Mode.saving
|
||||||
|
|
||||||
private weak var cheatsViewControllerDelegate: CheatsViewControllerDelegate?
|
private weak var cheatsViewControllerDelegate: CheatsViewControllerDelegate?
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ class PauseViewController: UIViewController, PauseInfoProvidable
|
|||||||
set { }
|
set { }
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var preferredContentSize = self.pauseNavigationController.topViewController?.preferredContentSize ?? CGSizeZero
|
var preferredContentSize = self.pauseNavigationController.topViewController?.preferredContentSize ?? CGSize.zero
|
||||||
if preferredContentSize.height > 0
|
if preferredContentSize.height > 0
|
||||||
{
|
{
|
||||||
preferredContentSize.height += self.pauseNavigationController.navigationBar.bounds.height
|
preferredContentSize.height += self.pauseNavigationController.navigationBar.bounds.height
|
||||||
@ -57,7 +57,7 @@ extension PauseViewController
|
|||||||
|
|
||||||
override func preferredStatusBarStyle() -> UIStatusBarStyle
|
override func preferredStatusBarStyle() -> UIStatusBarStyle
|
||||||
{
|
{
|
||||||
return .LightContent
|
return .lightContent
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidLayoutSubviews()
|
override func viewDidLayoutSubviews()
|
||||||
@ -68,11 +68,11 @@ extension PauseViewController
|
|||||||
self.pauseNavigationController.navigationBar.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.pauseNavigationController.navigationBar.bounds.height)
|
self.pauseNavigationController.navigationBar.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.pauseNavigationController.navigationBar.bounds.height)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func targetViewControllerForAction(action: Selector, sender: AnyObject?) -> UIViewController? {
|
override func targetViewController(forAction action: Selector, sender: AnyObject?) -> UIViewController? {
|
||||||
return self.pauseNavigationController
|
return self.pauseNavigationController
|
||||||
}
|
}
|
||||||
|
|
||||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
|
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
|
||||||
{
|
{
|
||||||
switch segue.identifier ?? ""
|
switch segue.identifier ?? ""
|
||||||
{
|
{
|
||||||
@ -80,7 +80,7 @@ extension PauseViewController
|
|||||||
self.pauseNavigationController = segue.destinationViewController as! UINavigationController
|
self.pauseNavigationController = segue.destinationViewController as! UINavigationController
|
||||||
self.pauseNavigationController.delegate = self
|
self.pauseNavigationController.delegate = self
|
||||||
self.pauseNavigationController.navigationBar.tintColor = UIColor.deltaLightPurpleColor()
|
self.pauseNavigationController.navigationBar.tintColor = UIColor.deltaLightPurpleColor()
|
||||||
self.pauseNavigationController.view.backgroundColor = UIColor.clearColor()
|
self.pauseNavigationController.view.backgroundColor = UIColor.clear()
|
||||||
|
|
||||||
let pauseMenuViewController = self.pauseNavigationController.topViewController as! PauseMenuViewController
|
let pauseMenuViewController = self.pauseNavigationController.topViewController as! PauseMenuViewController
|
||||||
pauseMenuViewController.items = self.items
|
pauseMenuViewController.items = self.items
|
||||||
@ -106,31 +106,31 @@ extension PauseViewController
|
|||||||
{
|
{
|
||||||
func dismiss()
|
func dismiss()
|
||||||
{
|
{
|
||||||
self.performSegueWithIdentifier("unwindFromPauseMenu", sender: self)
|
self.performSegue(withIdentifier: "unwindFromPauseMenu", sender: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func presentSaveStateViewControllerWithMode(mode: SaveStatesViewController.Mode, delegate: SaveStatesViewControllerDelegate)
|
func presentSaveStateViewControllerWithMode(_ mode: SaveStatesViewController.Mode, delegate: SaveStatesViewControllerDelegate)
|
||||||
{
|
{
|
||||||
self.saveStatesViewControllerMode = mode
|
self.saveStatesViewControllerMode = mode
|
||||||
self.saveStatesViewControllerDelegate = delegate
|
self.saveStatesViewControllerDelegate = delegate
|
||||||
|
|
||||||
self.performSegueWithIdentifier("saveStates", sender: self)
|
self.performSegue(withIdentifier: "saveStates", sender: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func presentCheatsViewController(delegate delegate: CheatsViewControllerDelegate)
|
func presentCheatsViewController(delegate: CheatsViewControllerDelegate)
|
||||||
{
|
{
|
||||||
self.cheatsViewControllerDelegate = delegate
|
self.cheatsViewControllerDelegate = delegate
|
||||||
|
|
||||||
self.performSegueWithIdentifier("cheats", sender: self)
|
self.performSegue(withIdentifier: "cheats", sender: self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension PauseViewController: UINavigationControllerDelegate
|
extension PauseViewController: UINavigationControllerDelegate
|
||||||
{
|
{
|
||||||
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?
|
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?
|
||||||
{
|
{
|
||||||
let transitionCoordinator = PauseTransitionCoordinator(presentationController: self.presentationController!)
|
let transitionCoordinator = PauseTransitionCoordinator(presentationController: self.presentationController!)
|
||||||
transitionCoordinator.presenting = (operation == .Push)
|
transitionCoordinator.presenting = (operation == .push)
|
||||||
return transitionCoordinator
|
return transitionCoordinator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,14 +25,14 @@ class PausePresentationController: UIPresentationController
|
|||||||
@IBOutlet private weak var pauseIconImageView: UIImageView!
|
@IBOutlet private weak var pauseIconImageView: UIImageView!
|
||||||
@IBOutlet private weak var stackView: UIStackView!
|
@IBOutlet private weak var stackView: UIStackView!
|
||||||
|
|
||||||
override init(presentedViewController: UIViewController, presentingViewController: UIViewController)
|
override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?)
|
||||||
{
|
{
|
||||||
self.blurringView = UIVisualEffectView(effect: nil)
|
self.blurringView = UIVisualEffectView(effect: nil)
|
||||||
self.vibrancyView = UIVisualEffectView(effect: nil)
|
self.vibrancyView = UIVisualEffectView(effect: nil)
|
||||||
|
|
||||||
super.init(presentedViewController: presentedViewController, presentingViewController: presentingViewController)
|
super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
|
||||||
|
|
||||||
self.contentView = NSBundle.mainBundle().loadNibNamed("PausePresentationControllerContentView", owner: self, options: nil).first as! UIView
|
self.contentView = Bundle.main.loadNibNamed("PausePresentationControllerContentView", owner: self, options: nil).first as! UIView
|
||||||
}
|
}
|
||||||
|
|
||||||
override func frameOfPresentedViewInContainerView() -> CGRect
|
override func frameOfPresentedViewInContainerView() -> CGRect
|
||||||
@ -44,7 +44,7 @@ class PausePresentationController: UIPresentationController
|
|||||||
|
|
||||||
if contentHeight == 0
|
if contentHeight == 0
|
||||||
{
|
{
|
||||||
let statusBarHeight = UIApplication.sharedApplication().statusBarFrame.height
|
let statusBarHeight = UIApplication.shared().statusBarFrame.height
|
||||||
frame = CGRect(x: 0, y: statusBarHeight, width: containerView.bounds.width, height: containerView.bounds.height - statusBarHeight)
|
frame = CGRect(x: 0, y: statusBarHeight, width: containerView.bounds.width, height: containerView.bounds.height - statusBarHeight)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -71,22 +71,22 @@ class PausePresentationController: UIPresentationController
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.blurringView.frame = self.containerView!.frame
|
self.blurringView.frame = self.containerView!.frame
|
||||||
self.blurringView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
|
self.blurringView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||||
self.containerView?.addSubview(self.blurringView)
|
self.containerView?.addSubview(self.blurringView)
|
||||||
|
|
||||||
self.vibrancyView.frame = self.containerView!.frame
|
self.vibrancyView.frame = self.containerView!.frame
|
||||||
self.vibrancyView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
|
self.vibrancyView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||||
self.containerView?.addSubview(self.vibrancyView)
|
self.containerView?.addSubview(self.vibrancyView)
|
||||||
|
|
||||||
self.contentView.alpha = 0.0
|
self.contentView.alpha = 0.0
|
||||||
self.vibrancyView.contentView.addSubview(self.contentView)
|
self.vibrancyView.contentView.addSubview(self.contentView)
|
||||||
|
|
||||||
self.presentingViewController.transitionCoordinator()?.animateAlongsideTransition({ context in
|
self.presentingViewController.transitionCoordinator()?.animate(alongsideTransition: { context in
|
||||||
|
|
||||||
let blurEffect = UIBlurEffect(style: .Dark)
|
let blurEffect = UIBlurEffect(style: .dark)
|
||||||
|
|
||||||
self.blurringView.effect = blurEffect
|
self.blurringView.effect = blurEffect
|
||||||
self.vibrancyView.effect = UIVibrancyEffect(forBlurEffect: blurEffect)
|
self.vibrancyView.effect = UIVibrancyEffect(blurEffect: blurEffect)
|
||||||
|
|
||||||
self.contentView.alpha = 1.0
|
self.contentView.alpha = 1.0
|
||||||
|
|
||||||
@ -95,22 +95,22 @@ class PausePresentationController: UIPresentationController
|
|||||||
|
|
||||||
override func dismissalTransitionWillBegin()
|
override func dismissalTransitionWillBegin()
|
||||||
{
|
{
|
||||||
self.presentingViewController.transitionCoordinator()?.animateAlongsideTransition({ context in
|
self.presentingViewController.transitionCoordinator()?.animate(alongsideTransition: { context in
|
||||||
self.blurringView.effect = nil
|
self.blurringView.effect = nil
|
||||||
self.vibrancyView.effect = nil
|
self.vibrancyView.effect = nil
|
||||||
self.contentView.alpha = 0.0
|
self.contentView.alpha = 0.0
|
||||||
}, completion: nil)
|
}, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func dismissalTransitionDidEnd(completed: Bool)
|
override func dismissalTransitionDidEnd(_ completed: Bool)
|
||||||
{
|
{
|
||||||
self.blurringView.removeFromSuperview()
|
self.blurringView.removeFromSuperview()
|
||||||
self.vibrancyView.removeFromSuperview()
|
self.vibrancyView.removeFromSuperview()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
|
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
|
||||||
{
|
{
|
||||||
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
|
super.viewWillTransition(to: size, with: coordinator)
|
||||||
|
|
||||||
// Super super hacky, but the system for some reason tries to layout the view in a (slightly) smaller space, which sometimes breaks constraints
|
// Super super hacky, but the system for some reason tries to layout the view in a (slightly) smaller space, which sometimes breaks constraints
|
||||||
// To fix this, we ensure there is enough room for the constraints to be valid temporarily, and then the frame will be fixed in containerViewDidLayoutSubviews()
|
// To fix this, we ensure there is enough room for the constraints to be valid temporarily, and then the frame will be fixed in containerViewDidLayoutSubviews()
|
||||||
@ -141,7 +141,7 @@ class PausePresentationController: UIPresentationController
|
|||||||
self.contentView.removeFromSuperview()
|
self.contentView.removeFromSuperview()
|
||||||
|
|
||||||
// Temporarily match the bounds of self.containerView (accounting for the status bar)
|
// Temporarily match the bounds of self.containerView (accounting for the status bar)
|
||||||
let statusBarHeight = UIApplication.sharedApplication().statusBarFrame.height
|
let statusBarHeight = UIApplication.shared().statusBarFrame.height
|
||||||
self.contentView.frame = CGRect(x: 0, y: statusBarHeight, width: self.containerView!.bounds.width, height: self.containerView!.bounds.height - statusBarHeight)
|
self.contentView.frame = CGRect(x: 0, y: statusBarHeight, width: self.containerView!.bounds.width, height: self.containerView!.bounds.height - statusBarHeight)
|
||||||
|
|
||||||
// Layout content view
|
// Layout content view
|
||||||
@ -163,7 +163,7 @@ class PausePresentationController: UIPresentationController
|
|||||||
self.presentedView()?.frame = self.frameOfPresentedViewInContainerView()
|
self.presentedView()?.frame = self.frameOfPresentedViewInContainerView()
|
||||||
|
|
||||||
// Unhide pauseIconImageView so its height is involved with layout calculations
|
// Unhide pauseIconImageView so its height is involved with layout calculations
|
||||||
self.pauseIconImageView.hidden = false
|
self.pauseIconImageView.isHidden = false
|
||||||
|
|
||||||
self.contentView.frame = CGRect(x: 0, y: statusBarHeight, width: self.containerView!.bounds.width, height: self.frameOfPresentedViewInContainerView().minY - statusBarHeight)
|
self.contentView.frame = CGRect(x: 0, y: statusBarHeight, width: self.containerView!.bounds.width, height: self.frameOfPresentedViewInContainerView().minY - statusBarHeight)
|
||||||
|
|
||||||
@ -173,11 +173,11 @@ class PausePresentationController: UIPresentationController
|
|||||||
let currentScaleFactor = self.pauseLabel.currentScaleFactor
|
let currentScaleFactor = self.pauseLabel.currentScaleFactor
|
||||||
if currentScaleFactor < self.pauseLabel.minimumScaleFactor || CGFloatEqualToFloat(currentScaleFactor, self.pauseLabel.minimumScaleFactor)
|
if currentScaleFactor < self.pauseLabel.minimumScaleFactor || CGFloatEqualToFloat(currentScaleFactor, self.pauseLabel.minimumScaleFactor)
|
||||||
{
|
{
|
||||||
self.pauseIconImageView.hidden = true
|
self.pauseIconImageView.isHidden = true
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self.pauseIconImageView.hidden = false
|
self.pauseIconImageView.isHidden = false
|
||||||
}
|
}
|
||||||
|
|
||||||
self.contentView.setNeedsLayout() // Ensures that layout will actually occur (sometimes the system thinks a layout is not needed, which messes up calculations)
|
self.contentView.setNeedsLayout() // Ensures that layout will actually occur (sometimes the system thinks a layout is not needed, which messes up calculations)
|
||||||
|
|||||||
@ -29,17 +29,17 @@ class SaveStatesCollectionHeaderView: UICollectionReusableView
|
|||||||
private func initialize()
|
private func initialize()
|
||||||
{
|
{
|
||||||
self.textLabel.translatesAutoresizingMaskIntoConstraints = false
|
self.textLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||||
self.textLabel.textColor = UIColor.whiteColor()
|
self.textLabel.textColor = UIColor.white()
|
||||||
|
|
||||||
var fontDescriptor = UIFontDescriptor.preferredFontDescriptorWithTextStyle(UIFontTextStyleTitle3)
|
var fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: UIFontTextStyleTitle3)
|
||||||
fontDescriptor = fontDescriptor.fontDescriptorWithSymbolicTraits([.TraitBold])
|
fontDescriptor = fontDescriptor.withSymbolicTraits([.traitBold])!
|
||||||
|
|
||||||
self.textLabel.font = UIFont(descriptor: fontDescriptor, size: 0.0)
|
self.textLabel.font = UIFont(descriptor: fontDescriptor, size: 0.0)
|
||||||
self.textLabel.textAlignment = .Center
|
self.textLabel.textAlignment = .center
|
||||||
self.addSubview(self.textLabel)
|
self.addSubview(self.textLabel)
|
||||||
|
|
||||||
// Auto Layout
|
// Auto Layout
|
||||||
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[textLabel]-20-|", options: [], metrics: nil, views: ["textLabel": self.textLabel]))
|
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "H:|-20-[textLabel]-20-|", options: [], metrics: nil, views: ["textLabel": self.textLabel]))
|
||||||
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-10-[textLabel]|", options: [], metrics: nil, views: ["textLabel": self.textLabel]))
|
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[textLabel]|", options: [], metrics: nil, views: ["textLabel": self.textLabel]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,24 +14,24 @@ import Roxas
|
|||||||
|
|
||||||
protocol SaveStatesViewControllerDelegate: class
|
protocol SaveStatesViewControllerDelegate: class
|
||||||
{
|
{
|
||||||
func saveStatesViewControllerActiveEmulatorCore(saveStatesViewController: SaveStatesViewController) -> EmulatorCore
|
func saveStatesViewControllerActiveEmulatorCore(_ saveStatesViewController: SaveStatesViewController) -> EmulatorCore
|
||||||
func saveStatesViewController(saveStatesViewController: SaveStatesViewController, updateSaveState saveState: SaveState)
|
func saveStatesViewController(_ saveStatesViewController: SaveStatesViewController, updateSaveState saveState: SaveState)
|
||||||
func saveStatesViewController(saveStatesViewController: SaveStatesViewController, loadSaveState saveState: SaveStateType)
|
func saveStatesViewController(_ saveStatesViewController: SaveStatesViewController, loadSaveState saveState: SaveStateType)
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SaveStatesViewController
|
extension SaveStatesViewController
|
||||||
{
|
{
|
||||||
enum Mode
|
enum Mode
|
||||||
{
|
{
|
||||||
case Saving
|
case saving
|
||||||
case Loading
|
case loading
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Section: Int
|
enum Section: Int
|
||||||
{
|
{
|
||||||
case Auto
|
case auto
|
||||||
case General
|
case general
|
||||||
case Locked
|
case locked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ class SaveStatesViewController: UICollectionViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var mode = Mode.Saving
|
var mode = Mode.saving
|
||||||
|
|
||||||
private var backgroundView: RSTBackgroundView!
|
private var backgroundView: RSTBackgroundView!
|
||||||
|
|
||||||
@ -51,21 +51,21 @@ class SaveStatesViewController: UICollectionViewController
|
|||||||
private var prototypeCellWidthConstraint: NSLayoutConstraint!
|
private var prototypeCellWidthConstraint: NSLayoutConstraint!
|
||||||
private var prototypeHeader = SaveStatesCollectionHeaderView()
|
private var prototypeHeader = SaveStatesCollectionHeaderView()
|
||||||
|
|
||||||
private var fetchedResultsController: NSFetchedResultsController!
|
private var fetchedResultsController: NSFetchedResultsController<AnyObject>!
|
||||||
|
|
||||||
private let imageOperationQueue = RSTOperationQueue()
|
private let imageOperationQueue = RSTOperationQueue()
|
||||||
private let imageCache = NSCache()
|
private let imageCache = Cache()
|
||||||
|
|
||||||
private var currentGameState: SaveStateType?
|
private var currentGameState: SaveStateType?
|
||||||
private var selectedSaveState: SaveState?
|
private var selectedSaveState: SaveState?
|
||||||
|
|
||||||
private let dateFormatter: NSDateFormatter
|
private let dateFormatter: DateFormatter
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder)
|
required init?(coder aDecoder: NSCoder)
|
||||||
{
|
{
|
||||||
self.dateFormatter = NSDateFormatter()
|
self.dateFormatter = DateFormatter()
|
||||||
self.dateFormatter.timeStyle = .ShortStyle
|
self.dateFormatter.timeStyle = .short
|
||||||
self.dateFormatter.dateStyle = .ShortStyle
|
self.dateFormatter.dateStyle = .short
|
||||||
|
|
||||||
super.init(coder: aDecoder)
|
super.init(coder: aDecoder)
|
||||||
}
|
}
|
||||||
@ -78,16 +78,16 @@ extension SaveStatesViewController
|
|||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
|
self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
|
||||||
self.backgroundView.hidden = true
|
self.backgroundView.isHidden = true
|
||||||
self.backgroundView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
|
self.backgroundView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||||
self.backgroundView.textLabel.text = NSLocalizedString("No Save States", comment: "")
|
self.backgroundView.textLabel.text = NSLocalizedString("No Save States", comment: "")
|
||||||
self.backgroundView.textLabel.textColor = UIColor.whiteColor()
|
self.backgroundView.textLabel.textColor = UIColor.white()
|
||||||
self.backgroundView.detailTextLabel.textColor = UIColor.whiteColor()
|
self.backgroundView.detailTextLabel.textColor = UIColor.white()
|
||||||
self.view.insertSubview(self.backgroundView, atIndex: 0)
|
self.view.insertSubview(self.backgroundView, at: 0)
|
||||||
|
|
||||||
let collectionViewLayout = self.collectionViewLayout as! GridCollectionViewLayout
|
let collectionViewLayout = self.collectionViewLayout as! GridCollectionViewLayout
|
||||||
let averageHorizontalInset = (collectionViewLayout.sectionInset.left + collectionViewLayout.sectionInset.right) / 2
|
let averageHorizontalInset = (collectionViewLayout.sectionInset.left + collectionViewLayout.sectionInset.right) / 2
|
||||||
let portraitScreenWidth = UIScreen.mainScreen().coordinateSpace.convertRect(UIScreen.mainScreen().bounds, toCoordinateSpace: UIScreen.mainScreen().fixedCoordinateSpace).width
|
let portraitScreenWidth = UIScreen.main().coordinateSpace.convert(UIScreen.main().bounds, to: UIScreen.main().fixedCoordinateSpace).width
|
||||||
|
|
||||||
// Use dimensions that allow two cells to fill the screen horizontally with padding in portrait mode
|
// Use dimensions that allow two cells to fill the screen horizontally with padding in portrait mode
|
||||||
// We'll keep the same size for landscape orientation, which will allow more to fit
|
// We'll keep the same size for landscape orientation, which will allow more to fit
|
||||||
@ -95,29 +95,29 @@ extension SaveStatesViewController
|
|||||||
|
|
||||||
switch self.mode
|
switch self.mode
|
||||||
{
|
{
|
||||||
case .Saving:
|
case .saving:
|
||||||
self.title = NSLocalizedString("Save State", comment: "")
|
self.title = NSLocalizedString("Save State", comment: "")
|
||||||
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can create a new save state by pressing the + button in the top right.", comment: "")
|
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can create a new save state by pressing the + button in the top right.", comment: "")
|
||||||
|
|
||||||
case .Loading:
|
case .loading:
|
||||||
self.title = NSLocalizedString("Load State", comment: "")
|
self.title = NSLocalizedString("Load State", comment: "")
|
||||||
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can create a new save state by pressing the Save State option in the pause menu.", comment: "")
|
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can create a new save state by pressing the Save State option in the pause menu.", comment: "")
|
||||||
self.navigationItem.rightBarButtonItem = nil
|
self.navigationItem.rightBarButtonItem = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manually update prototype cell properties
|
// Manually update prototype cell properties
|
||||||
self.prototypeCellWidthConstraint = self.prototypeCell.contentView.widthAnchor.constraintEqualToConstant(collectionViewLayout.itemWidth)
|
self.prototypeCellWidthConstraint = self.prototypeCell.contentView.widthAnchor.constraint(equalToConstant: collectionViewLayout.itemWidth)
|
||||||
self.prototypeCellWidthConstraint.active = true
|
self.prototypeCellWidthConstraint.isActive = true
|
||||||
|
|
||||||
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(SaveStatesViewController.handleLongPressGesture(_:)))
|
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(SaveStatesViewController.handleLongPressGesture(_:)))
|
||||||
self.collectionView?.addGestureRecognizer(longPressGestureRecognizer)
|
self.collectionView?.addGestureRecognizer(longPressGestureRecognizer)
|
||||||
|
|
||||||
self.registerForPreviewingWithDelegate(self, sourceView: self.collectionView!)
|
self.registerForPreviewing(with: self, sourceView: self.collectionView!)
|
||||||
|
|
||||||
self.updateBackgroundView()
|
self.updateBackgroundView()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(animated: Bool)
|
override func viewWillAppear(_ animated: Bool)
|
||||||
{
|
{
|
||||||
self.fetchedResultsController.performFetchIfNeeded()
|
self.fetchedResultsController.performFetchIfNeeded()
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ extension SaveStatesViewController
|
|||||||
super.viewWillAppear(animated)
|
super.viewWillAppear(animated)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidDisappear(animated: Bool)
|
override func viewDidDisappear(_ animated: Bool)
|
||||||
{
|
{
|
||||||
super.viewDidDisappear(animated)
|
super.viewDidDisappear(animated)
|
||||||
|
|
||||||
@ -149,8 +149,8 @@ private extension SaveStatesViewController
|
|||||||
|
|
||||||
let fetchRequest = SaveState.fetchRequest()
|
let fetchRequest = SaveState.fetchRequest()
|
||||||
fetchRequest.returnsObjectsAsFaults = false
|
fetchRequest.returnsObjectsAsFaults = false
|
||||||
fetchRequest.predicate = NSPredicate(format: "%K == %@", SaveState.Attributes.game.rawValue, game)
|
fetchRequest.predicate = Predicate(format: "%K == %@", SaveState.Attributes.game.rawValue, game)
|
||||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: SaveState.Attributes.type.rawValue, ascending: true), NSSortDescriptor(key: SaveState.Attributes.creationDate.rawValue, ascending: true)]
|
fetchRequest.sortDescriptors = [SortDescriptor(key: SaveState.Attributes.type.rawValue, ascending: true), SortDescriptor(key: SaveState.Attributes.creationDate.rawValue, ascending: true)]
|
||||||
|
|
||||||
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: SaveState.Attributes.type.rawValue, cacheName: nil)
|
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: SaveState.Attributes.type.rawValue, cacheName: nil)
|
||||||
self.fetchedResultsController.delegate = self
|
self.fetchedResultsController.delegate = self
|
||||||
@ -160,21 +160,21 @@ private extension SaveStatesViewController
|
|||||||
{
|
{
|
||||||
if let fetchedObjects = self.fetchedResultsController.fetchedObjects where fetchedObjects.count > 0
|
if let fetchedObjects = self.fetchedResultsController.fetchedObjects where fetchedObjects.count > 0
|
||||||
{
|
{
|
||||||
self.backgroundView.hidden = true
|
self.backgroundView.isHidden = true
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self.backgroundView.hidden = false
|
self.backgroundView.isHidden = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - Configure Views -
|
//MARK: - Configure Views -
|
||||||
|
|
||||||
func configureCollectionViewCell(cell: GridCollectionViewCell, forIndexPath indexPath: NSIndexPath, ignoreExpensiveOperations ignoreOperations: Bool = false)
|
func configureCollectionViewCell(_ cell: GridCollectionViewCell, forIndexPath indexPath: IndexPath, ignoreExpensiveOperations ignoreOperations: Bool = false)
|
||||||
{
|
{
|
||||||
let saveState = self.fetchedResultsController.objectAtIndexPath(indexPath) as! SaveState
|
let saveState = self.fetchedResultsController.object(at: indexPath) as! SaveState
|
||||||
|
|
||||||
cell.imageView.backgroundColor = UIColor.whiteColor()
|
cell.imageView.backgroundColor = UIColor.white()
|
||||||
cell.imageView.image = UIImage(named: "DeltaPlaceholder")
|
cell.imageView.image = UIImage(named: "DeltaPlaceholder")
|
||||||
|
|
||||||
if !ignoreOperations
|
if !ignoreOperations
|
||||||
@ -191,25 +191,25 @@ private extension SaveStatesViewController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure initially visible cells have loaded their image before they appear to prevent potential flickering from placeholder to thumbnail
|
// Ensure initially visible cells have loaded their image before they appear to prevent potential flickering from placeholder to thumbnail
|
||||||
if self.appearing
|
if self.isAppearing
|
||||||
{
|
{
|
||||||
imageOperation.immediate = true
|
imageOperation.isImmediate = true
|
||||||
}
|
}
|
||||||
|
|
||||||
self.imageOperationQueue.addOperation(imageOperation, forKey: indexPath)
|
self.imageOperationQueue.addOperation(imageOperation, forKey: indexPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
let dimensions = self.delegate.saveStatesViewControllerActiveEmulatorCore(self).preferredRenderingSize
|
let dimensions = self.delegate.saveStatesViewControllerActiveEmulatorCore(self).preferredRenderingSize
|
||||||
cell.maximumImageSize = CGSizeMake(self.prototypeCellWidthConstraint.constant, (self.prototypeCellWidthConstraint.constant / dimensions.width) * dimensions.height)
|
cell.maximumImageSize = CGSize(width: self.prototypeCellWidthConstraint.constant, height: (self.prototypeCellWidthConstraint.constant / dimensions.width) * dimensions.height)
|
||||||
|
|
||||||
cell.textLabel.textColor = UIColor.whiteColor()
|
cell.textLabel.textColor = UIColor.white()
|
||||||
cell.textLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
|
cell.textLabel.font = UIFont.preferredFont(forTextStyle: UIFontTextStyleSubheadline)
|
||||||
|
|
||||||
let name = saveState.name ?? self.dateFormatter.stringFromDate(saveState.modifiedDate)
|
let name = saveState.name ?? self.dateFormatter.string(from: saveState.modifiedDate)
|
||||||
cell.textLabel.text = name
|
cell.textLabel.text = name
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureCollectionViewHeaderView(headerView: SaveStatesCollectionHeaderView, forSection section: Int)
|
func configureCollectionViewHeaderView(_ headerView: SaveStatesCollectionHeaderView, forSection section: Int)
|
||||||
{
|
{
|
||||||
let section = self.correctedSectionForSectionIndex(section)
|
let section = self.correctedSectionForSectionIndex(section)
|
||||||
|
|
||||||
@ -217,9 +217,9 @@ private extension SaveStatesViewController
|
|||||||
|
|
||||||
switch section
|
switch section
|
||||||
{
|
{
|
||||||
case .Auto: title = NSLocalizedString("Auto Save", comment: "")
|
case .auto: title = NSLocalizedString("Auto Save", comment: "")
|
||||||
case .General: title = NSLocalizedString("General", comment: "")
|
case .general: title = NSLocalizedString("General", comment: "")
|
||||||
case .Locked: title = NSLocalizedString("Locked", comment: "")
|
case .locked: title = NSLocalizedString("Locked", comment: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
headerView.textLabel.text = title
|
headerView.textLabel.text = title
|
||||||
@ -227,15 +227,15 @@ private extension SaveStatesViewController
|
|||||||
|
|
||||||
//MARK: - Gestures -
|
//MARK: - Gestures -
|
||||||
|
|
||||||
@objc func handleLongPressGesture(gestureRecognizer: UILongPressGestureRecognizer)
|
@objc func handleLongPressGesture(_ gestureRecognizer: UILongPressGestureRecognizer)
|
||||||
{
|
{
|
||||||
guard gestureRecognizer.state == .Began else { return }
|
guard gestureRecognizer.state == .began else { return }
|
||||||
|
|
||||||
guard let indexPath = self.collectionView?.indexPathForItemAtPoint(gestureRecognizer.locationInView(self.collectionView)) else { return }
|
guard let indexPath = self.collectionView?.indexPathForItem(at: gestureRecognizer.location(in: self.collectionView)) else { return }
|
||||||
|
|
||||||
let saveState = self.fetchedResultsController.objectAtIndexPath(indexPath) as! SaveState
|
let saveState = self.fetchedResultsController.object(at: indexPath) as! SaveState
|
||||||
|
|
||||||
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
|
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||||
|
|
||||||
let actions = self.actionsForSaveState(saveState).map { $0.alertAction }
|
let actions = self.actionsForSaveState(saveState).map { $0.alertAction }
|
||||||
for action in actions
|
for action in actions
|
||||||
@ -243,7 +243,7 @@ private extension SaveStatesViewController
|
|||||||
alertController.addAction(action)
|
alertController.addAction(action)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.presentViewController(alertController, animated: true, completion: nil)
|
self.present(alertController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - Save States -
|
//MARK: - Save States -
|
||||||
@ -251,10 +251,10 @@ private extension SaveStatesViewController
|
|||||||
@IBAction func addSaveState()
|
@IBAction func addSaveState()
|
||||||
{
|
{
|
||||||
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
backgroundContext.performBlock {
|
backgroundContext.perform {
|
||||||
|
|
||||||
var game = self.delegate.saveStatesViewControllerActiveEmulatorCore(self).game as! Game
|
var game = self.delegate.saveStatesViewControllerActiveEmulatorCore(self).game as! Game
|
||||||
game = backgroundContext.objectWithID(game.objectID) as! Game
|
game = backgroundContext.object(with: game.objectID) as! Game
|
||||||
|
|
||||||
let saveState = SaveState.insertIntoManagedObjectContext(backgroundContext)
|
let saveState = SaveState.insertIntoManagedObjectContext(backgroundContext)
|
||||||
saveState.game = game
|
saveState.game = game
|
||||||
@ -263,17 +263,17 @@ private extension SaveStatesViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateSaveState(saveState: SaveState)
|
func updateSaveState(_ saveState: SaveState)
|
||||||
{
|
{
|
||||||
self.delegate?.saveStatesViewController(self, updateSaveState: saveState)
|
self.delegate?.saveStatesViewController(self, updateSaveState: saveState)
|
||||||
saveState.managedObjectContext?.saveWithErrorLogging()
|
saveState.managedObjectContext?.saveWithErrorLogging()
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadSaveState(saveState: SaveState)
|
func loadSaveState(_ saveState: SaveState)
|
||||||
{
|
{
|
||||||
let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self)
|
let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self)
|
||||||
|
|
||||||
if emulatorCore.state == .Stopped
|
if emulatorCore.state == .stopped
|
||||||
{
|
{
|
||||||
emulatorCore.startEmulation()
|
emulatorCore.startEmulation()
|
||||||
emulatorCore.pauseEmulation()
|
emulatorCore.pauseEmulation()
|
||||||
@ -282,47 +282,47 @@ private extension SaveStatesViewController
|
|||||||
self.delegate?.saveStatesViewController(self, loadSaveState: saveState)
|
self.delegate?.saveStatesViewController(self, loadSaveState: saveState)
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteSaveState(saveState: SaveState)
|
func deleteSaveState(_ saveState: SaveState)
|
||||||
{
|
{
|
||||||
let confirmationAlertController = UIAlertController(title: NSLocalizedString("Delete Save State?", comment: ""), message: NSLocalizedString("Are you sure you want to delete this save state? This cannot be undone.", comment: ""), preferredStyle: .Alert)
|
let confirmationAlertController = UIAlertController(title: NSLocalizedString("Delete Save State?", comment: ""), message: NSLocalizedString("Are you sure you want to delete this save state? This cannot be undone.", comment: ""), preferredStyle: .alert)
|
||||||
confirmationAlertController.addAction(UIAlertAction(title: NSLocalizedString("Delete", comment: ""), style: .Default, handler: { action in
|
confirmationAlertController.addAction(UIAlertAction(title: NSLocalizedString("Delete", comment: ""), style: .default, handler: { action in
|
||||||
|
|
||||||
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
backgroundContext.performBlock {
|
backgroundContext.perform {
|
||||||
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID)
|
let temporarySaveState = backgroundContext.object(with: saveState.objectID)
|
||||||
backgroundContext.deleteObject(temporarySaveState)
|
backgroundContext.delete(temporarySaveState)
|
||||||
backgroundContext.saveWithErrorLogging()
|
backgroundContext.saveWithErrorLogging()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}))
|
}))
|
||||||
confirmationAlertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil))
|
confirmationAlertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil))
|
||||||
|
|
||||||
self.presentViewController(confirmationAlertController, animated: true, completion: nil)
|
self.present(confirmationAlertController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renameSaveState(saveState: SaveState)
|
func renameSaveState(_ saveState: SaveState)
|
||||||
{
|
{
|
||||||
self.selectedSaveState = saveState
|
self.selectedSaveState = saveState
|
||||||
|
|
||||||
let alertController = UIAlertController(title: NSLocalizedString("Rename Save State", comment: ""), message: nil, preferredStyle: .Alert)
|
let alertController = UIAlertController(title: NSLocalizedString("Rename Save State", comment: ""), message: nil, preferredStyle: .alert)
|
||||||
alertController.addTextFieldWithConfigurationHandler { (textField) in
|
alertController.addTextField { (textField) in
|
||||||
textField.text = saveState.name
|
textField.text = saveState.name
|
||||||
textField.placeholder = NSLocalizedString("Name", comment: "")
|
textField.placeholder = NSLocalizedString("Name", comment: "")
|
||||||
textField.autocapitalizationType = .Words
|
textField.autocapitalizationType = .words
|
||||||
textField.returnKeyType = .Done
|
textField.returnKeyType = .done
|
||||||
textField.addTarget(self, action: #selector(SaveStatesViewController.updateSaveStateName(_:)), forControlEvents: .EditingDidEnd)
|
textField.addTarget(self, action: #selector(SaveStatesViewController.updateSaveStateName(_:)), for: .editingDidEnd)
|
||||||
}
|
}
|
||||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: { (action) in
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: { (action) in
|
||||||
self.selectedSaveState = nil
|
self.selectedSaveState = nil
|
||||||
}))
|
}))
|
||||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Rename", comment: ""), style: .Default, handler: { (action) in
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("Rename", comment: ""), style: .default, handler: { (action) in
|
||||||
self.updateSaveStateName(alertController.textFields!.first!)
|
self.updateSaveStateName(alertController.textFields!.first!)
|
||||||
}))
|
}))
|
||||||
self.presentViewController(alertController, animated: true, completion: nil)
|
self.present(alertController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func updateSaveStateName(textField: UITextField)
|
@objc func updateSaveStateName(_ textField: UITextField)
|
||||||
{
|
{
|
||||||
guard let selectedSaveState = self.selectedSaveState else { return }
|
guard let selectedSaveState = self.selectedSaveState else { return }
|
||||||
|
|
||||||
@ -334,9 +334,9 @@ private extension SaveStatesViewController
|
|||||||
}
|
}
|
||||||
|
|
||||||
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
backgroundContext.performBlock {
|
backgroundContext.perform {
|
||||||
|
|
||||||
let saveState = backgroundContext.objectWithID(selectedSaveState.objectID) as! SaveState
|
let saveState = backgroundContext.object(with: selectedSaveState.objectID) as! SaveState
|
||||||
saveState.name = text
|
saveState.name = text
|
||||||
|
|
||||||
backgroundContext.saveWithErrorLogging()
|
backgroundContext.saveWithErrorLogging()
|
||||||
@ -345,21 +345,21 @@ private extension SaveStatesViewController
|
|||||||
self.selectedSaveState = nil
|
self.selectedSaveState = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePreviewSaveState(saveState: SaveState?)
|
func updatePreviewSaveState(_ saveState: SaveState?)
|
||||||
{
|
{
|
||||||
let alertController = UIAlertController(title: NSLocalizedString("Change Preview Save State?", comment: ""), message: NSLocalizedString("The Preview Save State is loaded whenever you preview this game from the Main Menu with 3D Touch. Are you sure you want to change it?", comment: ""), preferredStyle: .Alert)
|
let alertController = UIAlertController(title: NSLocalizedString("Change Preview Save State?", comment: ""), message: NSLocalizedString("The Preview Save State is loaded whenever you preview this game from the Main Menu with 3D Touch. Are you sure you want to change it?", comment: ""), preferredStyle: .alert)
|
||||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil))
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil))
|
||||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Change", comment: ""), style: .Default, handler: { (action) in
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("Change", comment: ""), style: .default, handler: { (action) in
|
||||||
|
|
||||||
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
backgroundContext.performBlock {
|
backgroundContext.perform {
|
||||||
|
|
||||||
var game = self.delegate.saveStatesViewControllerActiveEmulatorCore(self).game as! Game
|
var game = self.delegate.saveStatesViewControllerActiveEmulatorCore(self).game as! Game
|
||||||
game = backgroundContext.objectWithID(game.objectID) as! Game
|
game = backgroundContext.object(with: game.objectID) as! Game
|
||||||
|
|
||||||
if let saveState = saveState
|
if let saveState = saveState
|
||||||
{
|
{
|
||||||
let previewSaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState
|
let previewSaveState = backgroundContext.object(with: saveState.objectID) as! SaveState
|
||||||
game.previewSaveState = previewSaveState
|
game.previewSaveState = previewSaveState
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -372,25 +372,25 @@ private extension SaveStatesViewController
|
|||||||
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
self.presentViewController(alertController, animated: true, completion: nil)
|
self.present(alertController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func lockSaveState(saveState: SaveState)
|
func lockSaveState(_ saveState: SaveState)
|
||||||
{
|
{
|
||||||
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
backgroundContext.performBlockAndWait() {
|
backgroundContext.performAndWait() {
|
||||||
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState
|
let temporarySaveState = backgroundContext.object(with: saveState.objectID) as! SaveState
|
||||||
temporarySaveState.type = .Locked
|
temporarySaveState.type = .locked
|
||||||
backgroundContext.saveWithErrorLogging()
|
backgroundContext.saveWithErrorLogging()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func unlockSaveState(saveState: SaveState)
|
func unlockSaveState(_ saveState: SaveState)
|
||||||
{
|
{
|
||||||
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
backgroundContext.performBlockAndWait() {
|
backgroundContext.performAndWait() {
|
||||||
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState
|
let temporarySaveState = backgroundContext.object(with: saveState.objectID) as! SaveState
|
||||||
temporarySaveState.type = .General
|
temporarySaveState.type = .general
|
||||||
backgroundContext.saveWithErrorLogging()
|
backgroundContext.saveWithErrorLogging()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -406,7 +406,7 @@ private extension SaveStatesViewController
|
|||||||
// Remove temporary save state file
|
// Remove temporary save state file
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
try NSFileManager.defaultManager().removeItemAtURL(saveState.fileURL)
|
try FileManager.default.removeItem(at: saveState.fileURL)
|
||||||
}
|
}
|
||||||
catch let error as NSError
|
catch let error as NSError
|
||||||
{
|
{
|
||||||
@ -447,7 +447,7 @@ private extension SaveStatesViewController
|
|||||||
|
|
||||||
//MARK: - Convenience Methods -
|
//MARK: - Convenience Methods -
|
||||||
|
|
||||||
func correctedSectionForSectionIndex(section: Int) -> Section
|
func correctedSectionForSectionIndex(_ section: Int) -> Section
|
||||||
{
|
{
|
||||||
let sectionInfo = self.fetchedResultsController.sections![section]
|
let sectionInfo = self.fetchedResultsController.sections![section]
|
||||||
let sectionIndex = Int(sectionInfo.name)!
|
let sectionIndex = Int(sectionInfo.name)!
|
||||||
@ -456,53 +456,53 @@ private extension SaveStatesViewController
|
|||||||
return section
|
return section
|
||||||
}
|
}
|
||||||
|
|
||||||
func actionsForSaveState(saveState: SaveState) -> [Action]
|
func actionsForSaveState(_ saveState: SaveState) -> [Action]
|
||||||
{
|
{
|
||||||
var actions = [Action]()
|
var actions = [Action]()
|
||||||
|
|
||||||
if self.traitCollection.forceTouchCapability == .Available
|
if self.traitCollection.forceTouchCapability == .available
|
||||||
{
|
{
|
||||||
if saveState.game.previewSaveState != saveState
|
if saveState.game.previewSaveState != saveState
|
||||||
{
|
{
|
||||||
let previewAction = Action(title: NSLocalizedString("Set as Preview Save State", comment: ""), style: .Default, action: { action in
|
let previewAction = Action(title: NSLocalizedString("Set as Preview Save State", comment: ""), style: .default, action: { action in
|
||||||
self.updatePreviewSaveState(saveState)
|
self.updatePreviewSaveState(saveState)
|
||||||
})
|
})
|
||||||
actions.append(previewAction)
|
actions.append(previewAction)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
let previewAction = Action(title: NSLocalizedString("Remove as Preview Save State", comment: ""), style: .Default, action: { action in
|
let previewAction = Action(title: NSLocalizedString("Remove as Preview Save State", comment: ""), style: .default, action: { action in
|
||||||
self.updatePreviewSaveState(nil)
|
self.updatePreviewSaveState(nil)
|
||||||
})
|
})
|
||||||
actions.append(previewAction)
|
actions.append(previewAction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let cancelAction = Action(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, action: nil)
|
let cancelAction = Action(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, action: nil)
|
||||||
actions.append(cancelAction)
|
actions.append(cancelAction)
|
||||||
|
|
||||||
let renameAction = Action(title: NSLocalizedString("Rename", comment: ""), style: .Default, action: { action in
|
let renameAction = Action(title: NSLocalizedString("Rename", comment: ""), style: .default, action: { action in
|
||||||
self.renameSaveState(saveState)
|
self.renameSaveState(saveState)
|
||||||
})
|
})
|
||||||
actions.append(renameAction)
|
actions.append(renameAction)
|
||||||
|
|
||||||
switch saveState.type
|
switch saveState.type
|
||||||
{
|
{
|
||||||
case .Auto: break
|
case .auto: break
|
||||||
case .General:
|
case .general:
|
||||||
let lockAction = Action(title: NSLocalizedString("Lock", comment: ""), style: .Default, action: { action in
|
let lockAction = Action(title: NSLocalizedString("Lock", comment: ""), style: .default, action: { action in
|
||||||
self.lockSaveState(saveState)
|
self.lockSaveState(saveState)
|
||||||
})
|
})
|
||||||
actions.append(lockAction)
|
actions.append(lockAction)
|
||||||
|
|
||||||
case .Locked:
|
case .locked:
|
||||||
let unlockAction = Action(title: NSLocalizedString("Unlock", comment: ""), style: .Default, action: { action in
|
let unlockAction = Action(title: NSLocalizedString("Unlock", comment: ""), style: .default, action: { action in
|
||||||
self.unlockSaveState(saveState)
|
self.unlockSaveState(saveState)
|
||||||
})
|
})
|
||||||
actions.append(unlockAction)
|
actions.append(unlockAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
let deleteAction = Action(title: NSLocalizedString("Delete", comment: ""), style: .Destructive, action: { action in
|
let deleteAction = Action(title: NSLocalizedString("Delete", comment: ""), style: .destructive, action: { action in
|
||||||
self.deleteSaveState(saveState)
|
self.deleteSaveState(saveState)
|
||||||
})
|
})
|
||||||
actions.append(deleteAction)
|
actions.append(deleteAction)
|
||||||
@ -514,20 +514,20 @@ private extension SaveStatesViewController
|
|||||||
//MARK: - <UIViewControllerPreviewingDelegate> -
|
//MARK: - <UIViewControllerPreviewingDelegate> -
|
||||||
extension SaveStatesViewController: UIViewControllerPreviewingDelegate
|
extension SaveStatesViewController: UIViewControllerPreviewingDelegate
|
||||||
{
|
{
|
||||||
func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?
|
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?
|
||||||
{
|
{
|
||||||
guard let indexPath = self.collectionView?.indexPathForItemAtPoint(location), layoutAttributes = self.collectionViewLayout.layoutAttributesForItemAtIndexPath(indexPath) else { return nil }
|
guard let indexPath = self.collectionView?.indexPathForItem(at: location), layoutAttributes = self.collectionViewLayout.layoutAttributesForItem(at: indexPath) else { return nil }
|
||||||
|
|
||||||
previewingContext.sourceRect = layoutAttributes.frame
|
previewingContext.sourceRect = layoutAttributes.frame
|
||||||
|
|
||||||
let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self)
|
let emulatorCore = self.delegate.saveStatesViewControllerActiveEmulatorCore(self)
|
||||||
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
||||||
|
|
||||||
let saveState = self.fetchedResultsController.objectAtIndexPath(indexPath) as! SaveState
|
let saveState = self.fetchedResultsController.object(at: indexPath) as! SaveState
|
||||||
|
|
||||||
let emulationViewController = storyboard.instantiateViewControllerWithIdentifier("emulationViewController") as! EmulationViewController
|
let emulationViewController = storyboard.instantiateViewController(withIdentifier: "emulationViewController") as! EmulationViewController
|
||||||
emulationViewController.game = emulatorCore.game as! Game
|
emulationViewController.game = emulatorCore.game as! Game
|
||||||
emulationViewController.overridePreviewActionItems = self.actionsForSaveState(saveState).filter{ $0.style != .Cancel }.map{ $0.previewAction }
|
emulationViewController.overridePreviewActionItems = self.actionsForSaveState(saveState).filter{ $0.style != .cancel }.map{ $0.previewAction }
|
||||||
emulationViewController.deferredPreparationHandler = { [unowned emulationViewController] in
|
emulationViewController.deferredPreparationHandler = { [unowned emulationViewController] in
|
||||||
|
|
||||||
// Store reference to current game state before we stop emulation so we can resume it if user decides to not load a save state
|
// Store reference to current game state before we stop emulation so we can resume it if user decides to not load a save state
|
||||||
@ -535,11 +535,11 @@ extension SaveStatesViewController: UIViewControllerPreviewingDelegate
|
|||||||
{
|
{
|
||||||
emulatorCore.saveSaveState() { saveState in
|
emulatorCore.saveSaveState() { saveState in
|
||||||
|
|
||||||
let fileURL = NSFileManager.uniqueTemporaryURL()
|
let fileURL = FileManager.uniqueTemporaryURL()
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
try NSFileManager.defaultManager().moveItemAtURL(saveState.fileURL, toURL: fileURL)
|
try FileManager.default.moveItem(at: saveState.fileURL, to: fileURL)
|
||||||
}
|
}
|
||||||
catch let error as NSError
|
catch let error as NSError
|
||||||
{
|
{
|
||||||
@ -572,7 +572,7 @@ extension SaveStatesViewController: UIViewControllerPreviewingDelegate
|
|||||||
return emulationViewController
|
return emulationViewController
|
||||||
}
|
}
|
||||||
|
|
||||||
func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController)
|
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController)
|
||||||
{
|
{
|
||||||
let emulationViewController = viewControllerToCommit as! EmulationViewController
|
let emulationViewController = viewControllerToCommit as! EmulationViewController
|
||||||
|
|
||||||
@ -598,29 +598,29 @@ extension SaveStatesViewController: UIViewControllerPreviewingDelegate
|
|||||||
//MARK: - <UICollectionViewDataSource> -
|
//MARK: - <UICollectionViewDataSource> -
|
||||||
extension SaveStatesViewController
|
extension SaveStatesViewController
|
||||||
{
|
{
|
||||||
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
|
override func numberOfSections(in collectionView: UICollectionView) -> Int
|
||||||
{
|
{
|
||||||
let numberOfSections = self.fetchedResultsController.sections!.count
|
let numberOfSections = self.fetchedResultsController.sections!.count
|
||||||
return numberOfSections
|
return numberOfSections
|
||||||
}
|
}
|
||||||
|
|
||||||
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
|
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
|
||||||
{
|
{
|
||||||
let section = self.fetchedResultsController.sections![section]
|
let section = self.fetchedResultsController.sections![section]
|
||||||
return section.numberOfObjects
|
return section.numberOfObjects
|
||||||
}
|
}
|
||||||
|
|
||||||
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
|
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
|
||||||
{
|
{
|
||||||
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(RSTGenericCellIdentifier, forIndexPath: indexPath) as! GridCollectionViewCell
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: RSTGenericCellIdentifier, for: indexPath) as! GridCollectionViewCell
|
||||||
self.configureCollectionViewCell(cell, forIndexPath: indexPath)
|
self.configureCollectionViewCell(cell, forIndexPath: indexPath)
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView
|
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
|
||||||
{
|
{
|
||||||
let headerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "Header", forIndexPath: indexPath) as! SaveStatesCollectionHeaderView
|
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Header", for: indexPath) as! SaveStatesCollectionHeaderView
|
||||||
self.configureCollectionViewHeaderView(headerView, forSection: indexPath.section)
|
self.configureCollectionViewHeaderView(headerView, forSection: (indexPath as NSIndexPath).section)
|
||||||
return headerView
|
return headerView
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -628,39 +628,39 @@ extension SaveStatesViewController
|
|||||||
//MARK: - <UICollectionViewDelegate> -
|
//MARK: - <UICollectionViewDelegate> -
|
||||||
extension SaveStatesViewController
|
extension SaveStatesViewController
|
||||||
{
|
{
|
||||||
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
|
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
|
||||||
{
|
{
|
||||||
let saveState = self.fetchedResultsController.objectAtIndexPath(indexPath) as! SaveState
|
let saveState = self.fetchedResultsController.object(at: indexPath) as! SaveState
|
||||||
|
|
||||||
switch self.mode
|
switch self.mode
|
||||||
{
|
{
|
||||||
case .Saving:
|
case .saving:
|
||||||
|
|
||||||
let section = self.correctedSectionForSectionIndex(indexPath.section)
|
let section = self.correctedSectionForSectionIndex((indexPath as NSIndexPath).section)
|
||||||
switch section
|
switch section
|
||||||
{
|
{
|
||||||
case .Auto: break
|
case .auto: break
|
||||||
case .General:
|
case .general:
|
||||||
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
backgroundContext.performBlockAndWait() {
|
backgroundContext.performAndWait() {
|
||||||
let temporarySaveState = backgroundContext.objectWithID(saveState.objectID) as! SaveState
|
let temporarySaveState = backgroundContext.object(with: saveState.objectID) as! SaveState
|
||||||
self.updateSaveState(temporarySaveState)
|
self.updateSaveState(temporarySaveState)
|
||||||
}
|
}
|
||||||
|
|
||||||
case .Locked:
|
case .locked:
|
||||||
let alertController = UIAlertController(title: NSLocalizedString("Cannot Modify Locked Save State", comment: ""), message: NSLocalizedString("This save state must first be unlocked before it can be modified.", comment: ""), preferredStyle: .Alert)
|
let alertController = UIAlertController(title: NSLocalizedString("Cannot Modify Locked Save State", comment: ""), message: NSLocalizedString("This save state must first be unlocked before it can be modified.", comment: ""), preferredStyle: .alert)
|
||||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .Cancel, handler: nil))
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .cancel, handler: nil))
|
||||||
self.presentViewController(alertController, animated: true, completion: nil)
|
self.present(alertController, animated: true, completion: nil)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case .Loading: self.loadSaveState(saveState)
|
case .loading: self.loadSaveState(saveState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func collectionView(collectionView: UICollectionView, didEndDisplayingCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath)
|
override func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
|
||||||
{
|
{
|
||||||
let operation = self.imageOperationQueue.operationForKey(indexPath)
|
let operation = self.imageOperationQueue.operation(forKey: indexPath)
|
||||||
operation?.cancel()
|
operation?.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -668,20 +668,20 @@ extension SaveStatesViewController
|
|||||||
//MARK: - <UICollectionViewDelegateFlowLayout> -
|
//MARK: - <UICollectionViewDelegateFlowLayout> -
|
||||||
extension SaveStatesViewController: UICollectionViewDelegateFlowLayout
|
extension SaveStatesViewController: UICollectionViewDelegateFlowLayout
|
||||||
{
|
{
|
||||||
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
|
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
|
||||||
{
|
{
|
||||||
// No need to load images from disk just to determine size, so we pass true for ignoreExpensiveOperations
|
// No need to load images from disk just to determine size, so we pass true for ignoreExpensiveOperations
|
||||||
self.configureCollectionViewCell(self.prototypeCell, forIndexPath: indexPath, ignoreExpensiveOperations: true)
|
self.configureCollectionViewCell(self.prototypeCell, forIndexPath: indexPath, ignoreExpensiveOperations: true)
|
||||||
|
|
||||||
let size = self.prototypeCell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
|
let size = self.prototypeCell.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize
|
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize
|
||||||
{
|
{
|
||||||
self.configureCollectionViewHeaderView(self.prototypeHeader, forSection: section)
|
self.configureCollectionViewHeaderView(self.prototypeHeader, forSection: section)
|
||||||
|
|
||||||
let size = self.prototypeHeader.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
|
let size = self.prototypeHeader.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -689,7 +689,7 @@ extension SaveStatesViewController: UICollectionViewDelegateFlowLayout
|
|||||||
//MARK: - <NSFetchedResultsControllerDelegate> -
|
//MARK: - <NSFetchedResultsControllerDelegate> -
|
||||||
extension SaveStatesViewController: NSFetchedResultsControllerDelegate
|
extension SaveStatesViewController: NSFetchedResultsControllerDelegate
|
||||||
{
|
{
|
||||||
func controllerDidChangeContent(controller: NSFetchedResultsController)
|
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
|
||||||
{
|
{
|
||||||
self.collectionView?.reloadData()
|
self.collectionView?.reloadData()
|
||||||
self.updateBackgroundView()
|
self.updateBackgroundView()
|
||||||
|
|||||||
@ -22,7 +22,7 @@ class PauseStoryboardSegue: UIStoryboardSegue
|
|||||||
override func perform()
|
override func perform()
|
||||||
{
|
{
|
||||||
self.destinationViewController.transitioningDelegate = self
|
self.destinationViewController.transitioningDelegate = self
|
||||||
self.destinationViewController.modalPresentationStyle = .Custom
|
self.destinationViewController.modalPresentationStyle = .custom
|
||||||
self.destinationViewController.modalPresentationCapturesStatusBarAppearance = true
|
self.destinationViewController.modalPresentationCapturesStatusBarAppearance = true
|
||||||
|
|
||||||
super.perform()
|
super.perform()
|
||||||
@ -31,17 +31,17 @@ class PauseStoryboardSegue: UIStoryboardSegue
|
|||||||
|
|
||||||
extension PauseStoryboardSegue: UIViewControllerTransitioningDelegate
|
extension PauseStoryboardSegue: UIViewControllerTransitioningDelegate
|
||||||
{
|
{
|
||||||
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning?
|
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?
|
||||||
{
|
{
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?
|
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?
|
||||||
{
|
{
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func presentationControllerForPresentedViewController(presentedViewController: UIViewController, presentingViewController: UIViewController, sourceViewController source: UIViewController) -> UIPresentationController?
|
func presentationController(forPresented presentedViewController: UIViewController, presenting presentingViewController: UIViewController?, source: UIViewController) -> UIPresentationController?
|
||||||
{
|
{
|
||||||
return self.presentationController
|
return self.presentationController
|
||||||
}
|
}
|
||||||
@ -49,20 +49,20 @@ extension PauseStoryboardSegue: UIViewControllerTransitioningDelegate
|
|||||||
|
|
||||||
extension PauseStoryboardSegue: UIViewControllerAnimatedTransitioning
|
extension PauseStoryboardSegue: UIViewControllerAnimatedTransitioning
|
||||||
{
|
{
|
||||||
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval
|
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval
|
||||||
{
|
{
|
||||||
return 0.65
|
return 0.65
|
||||||
}
|
}
|
||||||
|
|
||||||
func animateTransition(transitionContext: UIViewControllerContextTransitioning)
|
func animateTransition(using transitionContext: UIViewControllerContextTransitioning)
|
||||||
{
|
{
|
||||||
let destinationViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
|
let destinationViewController = transitionContext.viewController(forKey: UITransitionContextToViewControllerKey)!
|
||||||
|
|
||||||
destinationViewController.view.frame = transitionContext.finalFrameForViewController(destinationViewController)
|
destinationViewController.view.frame = transitionContext.finalFrame(for: destinationViewController)
|
||||||
destinationViewController.view.frame.origin.y = transitionContext.containerView()!.bounds.height
|
destinationViewController.view.frame.origin.y = transitionContext.containerView().bounds.height
|
||||||
transitionContext.containerView()!.addSubview(destinationViewController.view)
|
transitionContext.containerView().addSubview(destinationViewController.view)
|
||||||
|
|
||||||
UIView.animateWithDuration(self.transitionDuration(transitionContext), delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: [], animations: {
|
UIView.animate(withDuration: self.transitionDuration(using: transitionContext), delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: [], animations: {
|
||||||
|
|
||||||
// Calling layoutIfNeeded before the animation block for some reason prevents the blur from fading in
|
// Calling layoutIfNeeded before the animation block for some reason prevents the blur from fading in
|
||||||
// Additionally, if it's animated, it looks weird
|
// Additionally, if it's animated, it looks weird
|
||||||
|
|||||||
@ -21,25 +21,25 @@ class PauseTransitionCoordinator: NSObject, UIViewControllerAnimatedTransitionin
|
|||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval
|
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval
|
||||||
{
|
{
|
||||||
return 0.4
|
return 0.4
|
||||||
}
|
}
|
||||||
|
|
||||||
func animateTransition(transitionContext: UIViewControllerContextTransitioning)
|
func animateTransition(using transitionContext: UIViewControllerContextTransitioning)
|
||||||
{
|
{
|
||||||
let destinationViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
|
let destinationViewController = transitionContext.viewController(forKey: UITransitionContextToViewControllerKey)!
|
||||||
let sourceViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
|
let sourceViewController = transitionContext.viewController(forKey: UITransitionContextFromViewControllerKey)!
|
||||||
|
|
||||||
destinationViewController.view.frame = transitionContext.finalFrameForViewController(destinationViewController)
|
destinationViewController.view.frame = transitionContext.finalFrame(for: destinationViewController)
|
||||||
destinationViewController.view.frame.origin.y = self.presenting ? transitionContext.containerView()!.bounds.height : -destinationViewController.view.bounds.height
|
destinationViewController.view.frame.origin.y = self.presenting ? transitionContext.containerView().bounds.height : -destinationViewController.view.bounds.height
|
||||||
transitionContext.containerView()!.addSubview(destinationViewController.view)
|
transitionContext.containerView().addSubview(destinationViewController.view)
|
||||||
|
|
||||||
destinationViewController.view.layoutIfNeeded()
|
destinationViewController.view.layoutIfNeeded()
|
||||||
|
|
||||||
UIView.animateWithDuration(self.transitionDuration(transitionContext), delay:0, options:RSTSystemTransitionAnimationCurve, animations: {
|
UIView.animate(withDuration: self.transitionDuration(using: transitionContext), delay:0, options:RSTSystemTransitionAnimationCurve, animations: {
|
||||||
|
|
||||||
sourceViewController.view.frame.origin.y = self.presenting ? -sourceViewController.view.bounds.height : transitionContext.containerView()!.bounds.height
|
sourceViewController.view.frame.origin.y = self.presenting ? -sourceViewController.view.bounds.height : transitionContext.containerView().bounds.height
|
||||||
destinationViewController.view.frame.origin.y = 0
|
destinationViewController.view.frame.origin.y = 0
|
||||||
|
|
||||||
self.presentationController.containerView?.setNeedsLayout()
|
self.presentationController.containerView?.setNeedsLayout()
|
||||||
|
|||||||
@ -11,15 +11,15 @@ import DeltaCore
|
|||||||
|
|
||||||
private enum ControllersSettingsSection: Int
|
private enum ControllersSettingsSection: Int
|
||||||
{
|
{
|
||||||
case None
|
case none
|
||||||
case LocalDevice
|
case localDevice
|
||||||
case ExternalControllers
|
case externalControllers
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LocalDeviceController: ExternalController
|
private class LocalDeviceController: ExternalController
|
||||||
{
|
{
|
||||||
override var name: String {
|
override var name: String {
|
||||||
return UIDevice.currentDevice().name
|
return UIDevice.current().name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ class ControllersSettingsViewController: UITableViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var connectedControllers = ExternalControllerManager.sharedManager.connectedControllers.sort({ $0.playerIndex ?? NSIntegerMax < $1.playerIndex ?? NSIntegerMax })
|
private var connectedControllers = ExternalControllerManager.sharedManager.connectedControllers.sorted(isOrderedBefore: { $0.playerIndex ?? NSIntegerMax < $1.playerIndex ?? NSIntegerMax })
|
||||||
|
|
||||||
private lazy var localDeviceController: LocalDeviceController = {
|
private lazy var localDeviceController: LocalDeviceController = {
|
||||||
let device = LocalDeviceController()
|
let device = LocalDeviceController()
|
||||||
@ -52,8 +52,8 @@ class ControllersSettingsViewController: UITableViewController
|
|||||||
{
|
{
|
||||||
super.init(coder: aDecoder)
|
super.init(coder: aDecoder)
|
||||||
|
|
||||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ControllersSettingsViewController.externalControllerDidConnect(_:)), name: ExternalControllerDidConnectNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(ControllersSettingsViewController.externalControllerDidConnect(_:)), name: ExternalControllerDidConnectNotification, object: nil)
|
||||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ControllersSettingsViewController.externalControllerDidDisconnect(_:)), name: ExternalControllerDidDisconnectNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(ControllersSettingsViewController.externalControllerDidDisconnect(_:)), name: ExternalControllerDidDisconnectNotification, object: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidLoad()
|
override func viewDidLoad()
|
||||||
@ -63,7 +63,7 @@ class ControllersSettingsViewController: UITableViewController
|
|||||||
|
|
||||||
//MARK: - Storyboards -
|
//MARK: - Storyboards -
|
||||||
|
|
||||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
|
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
|
||||||
{
|
{
|
||||||
guard let indexPath = self.tableView.indexPathForSelectedRow else { return }
|
guard let indexPath = self.tableView.indexPathForSelectedRow else { return }
|
||||||
|
|
||||||
@ -71,18 +71,18 @@ class ControllersSettingsViewController: UITableViewController
|
|||||||
controllers.append(self.localDeviceController)
|
controllers.append(self.localDeviceController)
|
||||||
|
|
||||||
// Reset previous controller
|
// Reset previous controller
|
||||||
if let playerIndex = self.playerIndex, index = controllers.indexOf({ $0.playerIndex == playerIndex })
|
if let playerIndex = self.playerIndex, index = controllers.index(where: { $0.playerIndex == playerIndex })
|
||||||
{
|
{
|
||||||
let controller = controllers[index]
|
let controller = controllers[index]
|
||||||
controller.playerIndex = nil
|
controller.playerIndex = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ControllersSettingsSection(rawValue: indexPath.section)!
|
switch ControllersSettingsSection(rawValue: (indexPath as NSIndexPath).section)!
|
||||||
{
|
{
|
||||||
case .None: break
|
case .none: break
|
||||||
case .LocalDevice: self.localDeviceController.playerIndex = self.playerIndex
|
case .localDevice: self.localDeviceController.playerIndex = self.playerIndex
|
||||||
case .ExternalControllers:
|
case .externalControllers:
|
||||||
let controller = self.connectedControllers[indexPath.row]
|
let controller = self.connectedControllers[(indexPath as NSIndexPath).row]
|
||||||
controller.playerIndex = self.playerIndex
|
controller.playerIndex = self.playerIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,60 +93,60 @@ class ControllersSettingsViewController: UITableViewController
|
|||||||
|
|
||||||
private extension ControllersSettingsViewController
|
private extension ControllersSettingsViewController
|
||||||
{
|
{
|
||||||
dynamic func externalControllerDidConnect(notification: NSNotification)
|
dynamic func externalControllerDidConnect(_ notification: Notification)
|
||||||
{
|
{
|
||||||
guard let controller = notification.object as? ExternalController else { return }
|
guard let controller = notification.object as? ExternalController else { return }
|
||||||
|
|
||||||
if let playerIndex = controller.playerIndex
|
if let playerIndex = controller.playerIndex
|
||||||
{
|
{
|
||||||
self.connectedControllers.insert(controller, atIndex: playerIndex)
|
self.connectedControllers.insert(controller, at: playerIndex)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self.connectedControllers.append(controller)
|
self.connectedControllers.append(controller)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let index = self.connectedControllers.indexOf(controller)
|
if let index = self.connectedControllers.index(of: controller)
|
||||||
{
|
{
|
||||||
if self.connectedControllers.count == 1
|
if self.connectedControllers.count == 1
|
||||||
{
|
{
|
||||||
self.tableView.insertSections(NSIndexSet(index: ControllersSettingsSection.ExternalControllers.rawValue), withRowAnimation: .Fade)
|
self.tableView.insertSections(IndexSet(integer: ControllersSettingsSection.externalControllers.rawValue), with: .fade)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self.tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: index, inSection: ControllersSettingsSection.ExternalControllers.rawValue)], withRowAnimation: .Automatic)
|
self.tableView.insertRows(at: [IndexPath(row: index, section: ControllersSettingsSection.externalControllers.rawValue)], with: .automatic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic func externalControllerDidDisconnect(notification: NSNotification)
|
dynamic func externalControllerDidDisconnect(_ notification: Notification)
|
||||||
{
|
{
|
||||||
guard let controller = notification.object as? ExternalController else { return }
|
guard let controller = notification.object as? ExternalController else { return }
|
||||||
|
|
||||||
if let index = self.connectedControllers.indexOf(controller)
|
if let index = self.connectedControllers.index(of: controller)
|
||||||
{
|
{
|
||||||
self.connectedControllers.removeAtIndex(index)
|
self.connectedControllers.remove(at: index)
|
||||||
|
|
||||||
if self.connectedControllers.count == 0
|
if self.connectedControllers.count == 0
|
||||||
{
|
{
|
||||||
self.tableView.deleteSections(NSIndexSet(index: ControllersSettingsSection.ExternalControllers.rawValue), withRowAnimation: .Fade)
|
self.tableView.deleteSections(IndexSet(integer: ControllersSettingsSection.externalControllers.rawValue), with: .fade)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self.tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: index, inSection: ControllersSettingsSection.ExternalControllers.rawValue)], withRowAnimation: .Automatic)
|
self.tableView.deleteRows(at: [IndexPath(row: index, section: ControllersSettingsSection.externalControllers.rawValue)], with: .automatic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if controller.playerIndex == self.playerIndex
|
if controller.playerIndex == self.playerIndex
|
||||||
{
|
{
|
||||||
self.tableView.reloadSections(NSIndexSet(index: ControllersSettingsSection.None.rawValue), withRowAnimation: .None)
|
self.tableView.reloadSections(IndexSet(integer: ControllersSettingsSection.none.rawValue), with: .none)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ControllersSettingsViewController
|
extension ControllersSettingsViewController
|
||||||
{
|
{
|
||||||
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
|
override func numberOfSections(in tableView: UITableView) -> Int
|
||||||
{
|
{
|
||||||
if self.connectedControllers.count == 0
|
if self.connectedControllers.count == 0
|
||||||
{
|
{
|
||||||
@ -156,42 +156,42 @@ extension ControllersSettingsViewController
|
|||||||
return 3
|
return 3
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
|
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
|
||||||
{
|
{
|
||||||
switch ControllersSettingsSection(rawValue: section)!
|
switch ControllersSettingsSection(rawValue: section)!
|
||||||
{
|
{
|
||||||
case .None: return 1
|
case .none: return 1
|
||||||
case .LocalDevice: return 1
|
case .localDevice: return 1
|
||||||
case .ExternalControllers: return self.connectedControllers.count
|
case .externalControllers: return self.connectedControllers.count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
||||||
{
|
{
|
||||||
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
|
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
|
||||||
cell.detailTextLabel?.text = nil
|
cell.detailTextLabel?.text = nil
|
||||||
cell.accessoryType = .None
|
cell.accessoryType = .none
|
||||||
|
|
||||||
if indexPath.section == ControllersSettingsSection.None.rawValue
|
if (indexPath as NSIndexPath).section == ControllersSettingsSection.none.rawValue
|
||||||
{
|
{
|
||||||
cell.textLabel?.text = NSLocalizedString("None", comment: "")
|
cell.textLabel?.text = NSLocalizedString("None", comment: "")
|
||||||
|
|
||||||
if Settings.localControllerPlayerIndex != self.playerIndex && !self.connectedControllers.contains({ $0.playerIndex == self.playerIndex })
|
if Settings.localControllerPlayerIndex != self.playerIndex && !self.connectedControllers.contains({ $0.playerIndex == self.playerIndex })
|
||||||
{
|
{
|
||||||
cell.accessoryType = .Checkmark
|
cell.accessoryType = .checkmark
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
let controller: ExternalController
|
let controller: ExternalController
|
||||||
|
|
||||||
if indexPath.section == ControllersSettingsSection.LocalDevice.rawValue
|
if (indexPath as NSIndexPath).section == ControllersSettingsSection.localDevice.rawValue
|
||||||
{
|
{
|
||||||
controller = self.localDeviceController
|
controller = self.localDeviceController
|
||||||
}
|
}
|
||||||
else if indexPath.section == ControllersSettingsSection.ExternalControllers.rawValue
|
else if (indexPath as NSIndexPath).section == ControllersSettingsSection.externalControllers.rawValue
|
||||||
{
|
{
|
||||||
controller = self.connectedControllers[indexPath.row]
|
controller = self.connectedControllers[(indexPath as NSIndexPath).row]
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -202,7 +202,7 @@ extension ControllersSettingsViewController
|
|||||||
|
|
||||||
if controller.playerIndex == self.playerIndex
|
if controller.playerIndex == self.playerIndex
|
||||||
{
|
{
|
||||||
cell.accessoryType = .Checkmark
|
cell.accessoryType = .checkmark
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -217,13 +217,13 @@ extension ControllersSettingsViewController
|
|||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String?
|
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
|
||||||
{
|
{
|
||||||
switch ControllersSettingsSection(rawValue: section)!
|
switch ControllersSettingsSection(rawValue: section)!
|
||||||
{
|
{
|
||||||
case .None: return nil
|
case .none: return nil
|
||||||
case .LocalDevice: return NSLocalizedString("Local Device", comment: "")
|
case .localDevice: return NSLocalizedString("Local Device", comment: "")
|
||||||
case .ExternalControllers: return self.connectedControllers.count > 0 ? NSLocalizedString("External Controllers", comment: "") : ""
|
case .externalControllers: return self.connectedControllers.count > 0 ? NSLocalizedString("External Controllers", comment: "") : ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import DeltaCore
|
|||||||
|
|
||||||
private enum SettingsSection: Int
|
private enum SettingsSection: Int
|
||||||
{
|
{
|
||||||
case Controllers
|
case controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum SettingsSegues: String
|
private enum SettingsSegues: String
|
||||||
@ -25,8 +25,8 @@ class SettingsViewController: UITableViewController
|
|||||||
{
|
{
|
||||||
super.init(coder: aDecoder)
|
super.init(coder: aDecoder)
|
||||||
|
|
||||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SettingsViewController.externalControllerDidConnect(_:)), name: ExternalControllerDidConnectNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(SettingsViewController.externalControllerDidConnect(_:)), name: ExternalControllerDidConnectNotification, object: nil)
|
||||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SettingsViewController.externalControllerDidDisconnect(_:)), name: ExternalControllerDidDisconnectNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(SettingsViewController.externalControllerDidDisconnect(_:)), name: ExternalControllerDidDisconnectNotification, object: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidLoad()
|
override func viewDidLoad()
|
||||||
@ -34,13 +34,13 @@ class SettingsViewController: UITableViewController
|
|||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(animated: Bool)
|
override func viewWillAppear(_ animated: Bool)
|
||||||
{
|
{
|
||||||
super.viewWillAppear(animated)
|
super.viewWillAppear(animated)
|
||||||
|
|
||||||
if let indexPath = self.tableView.indexPathForSelectedRow
|
if let indexPath = self.tableView.indexPathForSelectedRow
|
||||||
{
|
{
|
||||||
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
|
self.tableView.deselectRow(at: indexPath, animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,54 +49,54 @@ class SettingsViewController: UITableViewController
|
|||||||
super.didReceiveMemoryWarning()
|
super.didReceiveMemoryWarning()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
|
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
|
||||||
{
|
{
|
||||||
if segue.identifier == SettingsSegues.Controllers.rawValue
|
if segue.identifier == SettingsSegues.Controllers.rawValue
|
||||||
{
|
{
|
||||||
let controllersSettingsViewController = segue.destinationViewController as! ControllersSettingsViewController
|
let controllersSettingsViewController = segue.destinationViewController as! ControllersSettingsViewController
|
||||||
controllersSettingsViewController.playerIndex = self.tableView.indexPathForSelectedRow?.row
|
controllersSettingsViewController.playerIndex = (self.tableView.indexPathForSelectedRow as NSIndexPath?)?.row
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension SettingsViewController
|
private extension SettingsViewController
|
||||||
{
|
{
|
||||||
@IBAction func unwindFromControllersSettingsViewController(segue: UIStoryboardSegue)
|
@IBAction func unwindFromControllersSettingsViewController(_ segue: UIStoryboardSegue)
|
||||||
{
|
{
|
||||||
let indexPath = self.tableView.indexPathForSelectedRow
|
let indexPath = self.tableView.indexPathForSelectedRow
|
||||||
|
|
||||||
self.tableView.reloadSections(NSIndexSet(index: SettingsSection.Controllers.rawValue), withRowAnimation: .None)
|
self.tableView.reloadSections(IndexSet(integer: SettingsSection.controllers.rawValue), with: .none)
|
||||||
|
|
||||||
self.tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: UITableViewScrollPosition.None)
|
self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: UITableViewScrollPosition.none)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension SettingsViewController
|
private extension SettingsViewController
|
||||||
{
|
{
|
||||||
dynamic func externalControllerDidConnect(notification: NSNotification)
|
dynamic func externalControllerDidConnect(_ notification: Notification)
|
||||||
{
|
{
|
||||||
self.tableView.reloadSections(NSIndexSet(index: SettingsSection.Controllers.rawValue), withRowAnimation: .None)
|
self.tableView.reloadSections(IndexSet(integer: SettingsSection.controllers.rawValue), with: .none)
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic func externalControllerDidDisconnect(notification: NSNotification)
|
dynamic func externalControllerDidDisconnect(_ notification: Notification)
|
||||||
{
|
{
|
||||||
self.tableView.reloadSections(NSIndexSet(index: SettingsSection.Controllers.rawValue), withRowAnimation: .None)
|
self.tableView.reloadSections(IndexSet(integer: SettingsSection.controllers.rawValue), with: .none)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SettingsViewController
|
extension SettingsViewController
|
||||||
{
|
{
|
||||||
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
||||||
{
|
{
|
||||||
let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
|
let cell = super.tableView(tableView, cellForRowAt: indexPath)
|
||||||
|
|
||||||
if indexPath.section == SettingsSection.Controllers.rawValue
|
if (indexPath as NSIndexPath).section == SettingsSection.controllers.rawValue
|
||||||
{
|
{
|
||||||
if indexPath.row == Settings.localControllerPlayerIndex
|
if (indexPath as NSIndexPath).row == Settings.localControllerPlayerIndex
|
||||||
{
|
{
|
||||||
cell.detailTextLabel?.text = UIDevice.currentDevice().name
|
cell.detailTextLabel?.text = UIDevice.current().name
|
||||||
}
|
}
|
||||||
else if let index = ExternalControllerManager.sharedManager.connectedControllers.indexOf({ $0.playerIndex == indexPath.row })
|
else if let index = ExternalControllerManager.sharedManager.connectedControllers.index(where: { $0.playerIndex == (indexPath as NSIndexPath).row })
|
||||||
{
|
{
|
||||||
let controller = ExternalControllerManager.sharedManager.connectedControllers[index]
|
let controller = ExternalControllerManager.sharedManager.connectedControllers[index]
|
||||||
cell.detailTextLabel?.text = controller.name
|
cell.detailTextLabel?.text = controller.name
|
||||||
@ -110,11 +110,11 @@ extension SettingsViewController
|
|||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
|
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
|
||||||
{
|
{
|
||||||
if indexPath.section == SettingsSection.Controllers.rawValue
|
if (indexPath as NSIndexPath).section == SettingsSection.controllers.rawValue
|
||||||
{
|
{
|
||||||
self.performSegueWithIdentifier(SettingsSegues.Controllers.rawValue, sender: self)
|
self.performSegue(withIdentifier: SettingsSegues.Controllers.rawValue, sender: self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
Pods/Pods.xcodeproj/project.pbxproj
generated
12
Pods/Pods.xcodeproj/project.pbxproj
generated
@ -232,6 +232,14 @@
|
|||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 0700;
|
LastSwiftUpdateCheck = 0700;
|
||||||
LastUpgradeCheck = 0700;
|
LastUpgradeCheck = 0700;
|
||||||
|
TargetAttributes = {
|
||||||
|
0A60B5C71D5A2CFF92811AA9AEC27278 = {
|
||||||
|
LastSwiftMigration = 0800;
|
||||||
|
};
|
||||||
|
B20CFA992EEA3E3A903F2359B05A88E1 = {
|
||||||
|
LastSwiftMigration = 0800;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */;
|
buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */;
|
||||||
compatibilityVersion = "Xcode 3.2";
|
compatibilityVersion = "Xcode 3.2";
|
||||||
@ -303,6 +311,7 @@
|
|||||||
PRODUCT_NAME = Pods;
|
PRODUCT_NAME = Pods;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
VERSION_INFO_PREFIX = "";
|
VERSION_INFO_PREFIX = "";
|
||||||
@ -328,6 +337,7 @@
|
|||||||
PRODUCT_NAME = FileMD5Hash;
|
PRODUCT_NAME = FileMD5Hash;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
VERSION_INFO_PREFIX = "";
|
VERSION_INFO_PREFIX = "";
|
||||||
@ -353,6 +363,7 @@
|
|||||||
PRODUCT_NAME = FileMD5Hash;
|
PRODUCT_NAME = FileMD5Hash;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
VERSION_INFO_PREFIX = "";
|
VERSION_INFO_PREFIX = "";
|
||||||
@ -420,6 +431,7 @@
|
|||||||
PRODUCT_NAME = Pods;
|
PRODUCT_NAME = Pods;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
VERSION_INFO_PREFIX = "";
|
VERSION_INFO_PREFIX = "";
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user