2016-02-27 65 views
1

我有一个用Swift编写的简单iOS应用程序,它使用CloudKit将字符串保存到云中。用户可以随时更新字符串(覆盖原始字符串)。这在我的代码中正常工作。如果用户在其他设备上更改字符串(例如,他们对iPad上的字符串进行更改,我希望他们的iPhone自动更新),我希望应用自动更新。我试图找到一个基本的CloudKit订阅教程,但它们都处理更高级的实现。我如何实现简单的CloudKit订阅?我的代码如下:实现基本的CloudKit订阅

import UIKit 
import CloudKit 

class ViewController: UIViewController { 

    // This the text field where the user inputs their string to save to the cloud 
    @IBOutlet weak var userInput1: UITextField! 

    // Save button 
    // When the user taps save, their string is saved to the cloud 
    @IBAction func saveButton(sender: AnyObject) { 

     let container = CKContainer.defaultContainer() 
     let privateDatabase = container.privateCloudDatabase 

     let myRecordName = "1001" 
     let recordID = CKRecordID(recordName: myRecordName) 

     privateDatabase.fetchRecordWithID(recordID, completionHandler: { (record, error) in 
      if error != nil { 

      } else { 
       record!.setObject(self.userInput1.text, forKey: "userInput1") 

       privateDatabase.saveRecord(record!, completionHandler: { (savedRecord, saveError) in 
        if saveError != nil { 
         print("Error saving record.") 
        } else { 
         print("Successfully updated record!") 
        } 
       }) 
      } 
     }) 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // Auto populates app with cloud string 
     let container = CKContainer.defaultContainer() 
     let privateDatabase = container.privateCloudDatabase 

     let myRecordName = "1001" 
     let recordID = CKRecordID(recordName: myRecordName) 

     privateDatabase.fetchRecordWithID(recordID, completionHandler: { (record, error) in 

      if error != nil { 
       // Nothing saved to cloud yet 
       print(error) 
      } else { 
       // Display record 
       dispatch_async(dispatch_get_main_queue()) { 
        self.userInput1.text = (record!["userInput1"]! as! String) 
       } 
      } 
     }) 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
    } 
} 

回答

1

订阅有两部分;第一个保存订阅,第二个代码在启动时触发。此代码使用自己的CKRecordID创建订阅,比它需要的复杂一点。它也触发更新和删除,还有第三种选择。创建。是的,它在公共数据库中,你目前在私人数据库中。所以你做出了一些改变,这是一个挑战。

func subscribe4Cloud() { 
let container = CKContainer(identifier: "iCloud.com") 
let publicDB = container.publicCloudDatabase 
let predicateY = NSPredicate(value: true) 
let query = CKQuery(recordType: "Collections", predicate: predicateY) 
publicDB.performQuery(query, inZoneWithID: nil) { 
    records, error in 
    if error != nil { 
     print("twang this is broken \(error)") 
    } else { 
     if records!.count > 0 { 
       subID = String(NSUUID().UUIDString) 
       let predicateY = NSPredicate(value: true) 
       let subscription = CKSubscription(recordType: "Collections", predicate: predicateY, subscriptionID: subID, options: [.FiresOnRecordUpdate, .FiresOnRecordDeletion]) 
       subscription.notificationInfo = CKNotificationInfo() 

       publicDB.saveSubscription(subscription) { 
        subscription, error in 
        if error != nil { 
         print("ping sub failed, almost certainly cause it is already there \(theLink) \(error)") 
        } else { 
         print("bing subscription saved! \(subID) ") 
        } 
       } 
     } else { 
      print("no records found") 
     } 
    } 
} 

}

这是第一部分。凯特:你可能会错过的一个关键点[我确实]。一旦你保存了订阅;你不需要再做一次;你只需要运行一次。

您也可以在CloudKit仪表板中执行此操作。第二部分是设置您的应用程序委托来获取订阅,您可以通过添加此方法来完成订阅。

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler:() -> Void) { 
    if application.applicationState == .Inactive { 
     // Do nothing 
    } 
    let notification = CKQueryNotification(fromRemoteNotificationDictionary: userInfo as! [String : NSObject]) 
    let container = CKContainer(identifier: "iCloud.com") 
    let publicDB = container.publicCloudDatabase 

    if notification.notificationType == .Query { 
     let queryNotification = notification as! CKQueryNotification 
     if queryNotification.queryNotificationReason == .RecordUpdated { 
      print("queryNotification.recordID \(queryNotification.recordID)") 
     } 
    } 
    print("userInfo \(userInfo)") 
} 

此处可能有几行代码不是严格需要的;我从我工作过的一个项目中剔除了这个。

此代码将启动您;我几乎毫不费力地查看通过发送通知,而不是打印它。你需要解析它,看看你感兴趣的位。

你的第三个挑战是实现KVO或NSNotifications甚至委托从这里获取消息到你的代码中的其他类;所以从应用程序委托你的视图控制器在你的情况!

使用cloudKit并不容易,它是一个尝试和学习编码的好地方,它可能是一个真正的挑战,一个很好的方式可以学习一些非常重要的编码原则,实践和技巧。

+0

谢谢你的信息...我现在有点工作了.. 。我有我的iPhone插入,我正在iPhone上的Xcode测试应用程序。当我通过CloudKit Dashboard进行记录更新时,我收到一条通知,表示记录“XYZ”已更新。只需确认,该通知实际上并不包含更新的记录?它只包含更新的记录的ID? – user1822824

1

你可以使用CloudKit订阅保存这个字符串,但是如果你只是寻找一个简单的方法来保存跨单一的iCloud用户的设备坚持,我肯定会建议只使用NSUbiquitousKeyValueStore一个字符串,它的工作原理是NSUserDefaults但跨所有iCloud用户的设备。要打开此商店,只需转到项目设置的“功能”部分。启用iCloud并检查“键值存储”框。

在代码中使用,这是简单的:

NSUbiquitousKeyValueStore.defaultStore().setObject("the user's string", forKey: "userString")

let userString = NSUbiquitousKeyValueStore.defaultStore().objectForKey("userString") as? String

如果你想获得实时通知,当键值存储的变化,只是听为NSUbiquitousKeyValueStoreDidChangeExternallyNotification