Setting up
- Go to Xcode and go to the capabilities section under your app's settings. You should set it up to look like this (most of which will automatically be done by Apple when you turn CloudKit on):
- Go to your CloudKit dashboard and set up how you want your data to be stored by adding records. You can also add data to your public/private databases!
The Code
Surprisingly, there is also minimal code. Working with our previous records that we created in the CloudKit dashboard. This is the only code we require to fetch and update highscores (excuse the poor layout, I'm working with limited space):// CloudKitManager.swift // Angle Reader // // Created by Chelsea Farley on 7/02/15. // Copyright (c) 2015 Trip Wire. All rights reserved. // import CloudKit class CloudKitManager { var container : CKContainer! var isICloudAvailable : Bool = false var highscore : CKRecord! init() { // container which is used to access private // and public databases container = CKContainer.defaultContainer() } func fetchRecord(mode: String) { if (self.isICloudAvailable) { let predicate = NSPredicate(format: "Mode = %@", mode) let query = CKQuery(recordType: "Highscores", predicate: predicate) // load the highscore record with the matching mode container.privateCloudDatabase.performQuery(query, inZoneWithID: nil, completionHandler: ({results, error in var length = results!.count if (error == nil && results!.count > 0) { self.highscore = results[0] as! CKRecord } else { // create a highscore record if none exists var record = CKRecord(recordType: "Highscores") record.setObject(mode as CKRecordValue, forKey: "Mode") record.setObject(0 as CKRecordValue, forKey: "Highscore") self.container.privateCloudDatabase.saveRecord( record, completionHandler: ({result, error in if (error == nil) { self.highscore = result } })) } })) } } func updateHighscore(score: Int) -> Int { if (self.isICloudAvailable) { if (highscore != nil ) { var highscoreValue = highscore .valueForKey("Highscore") as! Int if (highscoreValue < score) { highscore.setObject(score as CKRecordValue, forKey: "Highscore") self.container.privateCloudDatabase.saveRecord (highscore, completionHandler: nil) } return highscoreValue } } return 0 } }
The above code handles loading, creating and updating highscores. I have put this in its own class as I believe this avoids it complicating game logic. There were also some minor adjustments required in the GameViewController, I will only show the code I added:
// GameViewController.swift // Angle Reader // // Created by Chelsea Farley on 7/02/15. // Copyright (c) 2015 Trip Wire. All rights reserved. // import UIKit import CloudKit import SpriteKit class GameViewController : UIViewController { var ckManager : CloudKitManager! override func viewDidLoad() { // Standard code represented by ... ... ckManager = CloudKitManager() NSNotificationCenter.defaultCenter().addObserver(self, selector: "applicationBecameActive:", name: UIApplicationDidBecomeActiveNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: "applicationBecameInactive:", name: UIApplicationWillResignActiveNotification, object: nil) } func handleIdentityChanged(notification: NSNotification){ let fileManager = NSFileManager() if let token = fileManager.ubiquityIdentityToken{ ckManager.isICloudAvailable = true } else { ckManager.isICloudAvailable = false } } func applicationBecameActive(notification: NSNotification){ NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleIdentityChanged:", name: NSUbiquityIdentityDidChangeNotification, object: nil) } func applicationBecameInactive(notification: NSNotification){ NSNotificationCenter.defaultCenter().removeObserver(self, name: NSUbiquityIdentityDidChangeNotification, object: nil) } override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) ckManager.container.accountStatusWithCompletionHandler{ [weak self] (status: CKAccountStatus, error: NSError!) in // Be careful, we might be on a different thread // so make sure that your UI operations go // on the main thread dispatch_async(dispatch_get_main_queue(), { if error == nil{ self!.ckManager.isICloudAvailable = status == .Available } }) } } }
The above code is all you need to identify whether iCloud is currently available, and it updates every time you exit or enter the application.
No comments:
Post a Comment