【Swift 学习笔记】iCloud:Key-Value Storage

【Swift 学习笔记】iCloud:Key-Value Storage

想让自己的程序支持iCloud。搜索发现OC的教程比较多。照猫画虎,翻译+整理一个swift版本的。
参考:http://code.tutsplus.com/tutorials/working-with-icloud-key-value-storage--pre-37542

开始之前

需要一个付费的iOS 开发者账号。
至少要2台iOS设备才可以测试数据同步功能。(iOS Simulator无法做iCloud Storage的测试)

如果你手头没有iOS开发者账号,或者没有2台iOS设备。这篇文章还是可以让你了解如何配置iCloud的,如何使用iCloud让你的程序变得更好。

Step 1:新建一个项目

首先需要对本地Xcode中的项目进行配置。

1.png

用创建一个新的项目。
template: Single View Application project
name: iCloudKeyValue
Language: Swift

Step 2: 配置iCloud

在Xcode 6中,配置iCloud比较简单。

在Project Navigator 中选择项目。在Capabilities中将iCloud的switch开关设置为On。

3.png

Xcode会自动帮你 创建App ID,将Entitlements权限文件添加到项目中

5.png
  • 进入开发者中心
  • 点击右上角的“Certificates, Identifiers & Profiles”
  • 在新的页面中,选择“Provisioning Profiles”
  • 在新页面中选择App IDs。可以看到,通过刚才的步骤a,Xcode已经自动创建了App ID: brincell.iCloudKeyValue
  • 点击这个App ID,展开。你会发现iCloud 服务处于Configurable状态。
appIDConfiguarbel.png

(以Key-Value Storage来使用iCloud,不需要iCloud Container文件。所以这里是需要配置的状态。)

Step 3: demo 程序

demo 用的是Apple官方教程YourFirstApp
稍加修改,改为iOS App。

Screen Shot 2015-01-07 at 11.33.32 AM.png
class Track: NSObject {
  var volume : Float = 0
}

class ViewController: UIViewController {
  let track = Track()
 
 
  @IBOutlet weak var textField: UITextField!
  @IBOutlet weak var slider: UISlider!
 
  @IBAction func mute(sender: AnyObject) {
    track.volume = 0.0
    updateUserInterface()
    println("click mute button")
  }

  @IBAction func textField(sender: AnyObject) {
    var newValue = slider.value
    track.volume = newValue
    updateUserInterface()
    println("\(slider.value)")
  }

  func updateUserInterface() {
    var volume = track.volume
    self.textField.text = "\(volume)"
    self.slider.value = volume
  }
}

运行程序。测试slider和Mute按钮能否正常工作。拖动slider,textField显示对应的值。

Step 4. 保存数据和加载数据

现在在手机上退出重启程序,数据是无法保存的。
我们这里用user defaults database 来保存数据。

添加saveVolume() loadVolume() 两个方法。

func saveVolume() {
    let ud = NSUserDefaults.standardUserDefaults()
    let trackVolume = track.volume
    ud.setValue(trackVolume, forKey: "Track")
}

func loadVolume(){
    let ud = NSUserDefaults.standardUserDefaults()
    if ud.valueForKey("Track") != nil {
        track.volume = ud.valueForKey("Track") as Float
    } else {
        track.volume = 5
    }
}

在viewDidLoad() 中调用loadVolume()。在Mute和Slider的action中调用saveVolume()方法。

class ViewController: UIViewController {
  let track = Track()
 
 
  @IBOutlet weak var textField: UITextField!
  @IBOutlet weak var slider: UISlider!
 
  @IBAction func mute(sender: AnyObject) {
    track.volume = 0.0
    updateUserInterface()
    saveVolume()
    println("click mute button")
  }

  @IBAction func textField(sender: AnyObject) {
    var newValue = slider.value
    track.volume = newValue
    updateUserInterface()
    saveVolume()
    println("\(slider.value)")
  }

  func updateUserInterface() {
    var volume = track.volume
    self.textField.text = "\(volume)"
    self.slider.value = volume
  }
 
  override func viewDidLoad() {
    super.viewDidLoad()
    loadVolume()
    updateUserInterface()

  }
   
    func saveVolume() {
        let ud = NSUserDefaults.standardUserDefaults()
        let trackVolume = track.volume
        ud.setValue(trackVolume, forKey: "Track")      
    }

    func loadVolume(){
        let ud = NSUserDefaults.standardUserDefaults()
        if ud.valueForKey("Track") != nil {
            track.volume = ud.valueForKey("Track") as Float
        } else {
            track.volume = 5
        }
    }
}

运行程序。双击Home,在程序列表中上划完全退出demo。重新启动demo看是否能够成功保存数据。

Step 5. iCloud 同步数据

为了让demo程序更加好用,我们用iCloud来同步设备间的数据。这个过程非常的简单。
iCloud's Key-Value Storage 和 NSUserDefaults 用法非常的像,也是存储key-value键值对。iCloud对应的类叫做 NSUbiquitousKeyValueStore。

我们先来实现iCloud的存储。
在saveVolume() 方法中,仿造NSUserDefaults写NSUbiquitousKeyValueStore方法。(注:NSUserDefaults可以用setValue方法来存储。NSUbiquitousKeyValueStore用这个方法程序缺一直crash。不知道是swift的坑还是什么。这里先转换成double值,用setDouble试一下。)

func saveVolume() {
    let ud = NSUserDefaults.standardUserDefaults()
    let trackVolume = track.volume
    ud.setValue(trackVolume, forKey: "Track")
   
    // Save to iCloud
    let store = NSUbiquitousKeyValueStore.defaultStore()
    let trackVolumeDouble = Double(trackVolume)
    store.setDouble(trackVolumeDouble, forKey: "Track")
    store.synchronize()
    println("Saving to iCloud")
   
}

那么我们的demo程序是如何知道其他设备中的程序已经改变了iCloud 中的Key-Value,把改动同步到当前设备的呢?
每当 Key-Value 被改变,程序会发送一个notification出来,我们的程序收到这个notification,把数据覆盖到本地就可以了。

在 viewDidLoad() 中做4件事。

  1. 首先得到Key-Value Store的引用。

  2. 把我们的View Controller当做一个监听器。监听NSUbiquitousKeyValueStoreDidChangeExternallyNotification
    当接受到这个notification的时候,用updateKeyValuePairs: 方法来处理它。

  3. 给store发送一个synchronize消息。

  4. 刷新数据

     override func viewDidLoad() {
     super.viewDidLoad()
    
     let store = NSUbiquitousKeyValueStore.defaultStore()
     NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("updateKeyValuePairs:"), name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification, object: store)
     store.synchronize()
     loadVolume()
     updateUserInterface()
    
    }
    
    func updateKeyValuePairs(notification: NSNotification) {
     println("updateKeyValuePairs")
     let userInfo = notification.userInfo
     let changeReason: AnyObject? = userInfo?["NSUbiquitousKeyValueStoreChangeReasonKey"]
     var reason = -1
    

    if (changeReason == nil) {
    return
    } else {
    reason = changeReason as Int
    println("reason is: (reason)")
    }

     if (reason == NSUbiquitousKeyValueStoreServerChange) || (reason == NSUbiquitousKeyValueStoreInitialSyncChange) {
       let changeKeys = userInfo?["NSUbiquitousKeyValueStoreChangedKeysKey"] as NSArray
       let store = NSUbiquitousKeyValueStore.defaultStore()
      
       for key in changeKeys {
         if key.isEqualToString("Track") {
           // Update Data Source
           let trackVolumeFromStore = store.doubleForKey("Track") as Double
           println("track volume from store: \(trackVolumeFromStore)")
           // Save Local Copy
           track.volume = Float(trackVolumeFromStore)
           let ud = NSUserDefaults.standardUserDefaults()
           ud.setValue(trackVolumeFromStore, forKey: "Track")
          
           updateUserInterface()
         }
       }
     }
    

    }

在两台设备中运行程序。改变一台设备的数据。观察另一台设备的打印日志。可以看到它接受到通知,调用了
updateKeyValuePairs:

GitHub:

https://github.com/vivijie/iCloudTest

参考文献:

http://code.tutsplus.com/tutorials/working-with-icloud-key-value-storage--pre-37542

https://developer.apple.com/library/ios/documentation/General/Conceptual/iCloudDesignGuide/Chapters/Introduction.html#//apple_ref/doc/uid/TP40012094

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容

  • PLEASE READ THE FOLLOWING APPLE DEVELOPER PROGRAM LICENSE...
    念念不忘的阅读 13,413评论 5 6
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • 当早晨第一缕阳光透过木窗,穿过海蓝色窗帘的星星点点,洒在我的脸上。 阳光暖暖,就像冬日里手里的一杯咖啡,舍不...
    路过江南飘雪阅读 208评论 0 2
  • 除了听闻你喜风尘女子,而我一生只能疯癫。还听闻他的痴情,而我只信感觉。 欠他的终究却给了你。一报还一报。 不喜争吵...
    胡biubiu阅读 259评论 5 1
  • 原文地址 代码可读性 格式和测试 格式 读代码就像是读文章、小说、新闻 阅读的顺序一般来说都是从上到下,从左到右 ...
    woodccc阅读 451评论 0 0