我有一个用Swift编写的简单iOS应用程序,它使用CloudKit将字符串保存到云端。用户可以随时更新字符串(覆盖原始字符串)。这在我的代码中工作正常。我希望应用程序在用户更改其他设备上的字符串时自动更新(假设他们在iPad上更改了字符串,我希望他们的iPhone能够自动更新)。我试图找到一个基本的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()
}
}
答案 0 :(得分: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的第三个挑战,甚至是代表,从此处获取消息到代码中的其他类;所以从app委托给你的视图控制器!
使用cloudKit并不容易,它是尝试和学习编码的好地方,它可以是一个真正的挑战,也是学习一些非常重要的编码原则,实践和技术的好方法。
答案 1 :(得分: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