鍍金池/ 教程/ iOS/ iCloud 和 Core Data
與四軸無人機(jī)的通訊
在沙盒中編寫腳本
結(jié)構(gòu)體和值類型
深入理解 CocoaPods
UICollectionView + UIKit 力學(xué)
NSString 與 Unicode
代碼簽名探析
測試
架構(gòu)
第二期-并發(fā)編程
Metal
自定義控件
iOS 中的行為
行為驅(qū)動開發(fā)
Collection View 動畫
截圖測試
MVVM 介紹
使 Mac 應(yīng)用數(shù)據(jù)腳本化
一個完整的 Core Data 應(yīng)用
插件
字符串
為 iOS 建立 Travis CI
先進(jìn)的自動布局工具箱
動畫
為 iOS 7 重新設(shè)計(jì) App
XPC
從 NSURLConnection 到 NSURLSession
Core Data 網(wǎng)絡(luò)應(yīng)用實(shí)例
GPU 加速下的圖像處理
自定義 Core Data 遷移
子類
與調(diào)試器共舞 - LLDB 的華爾茲
圖片格式
并發(fā)編程:API 及挑戰(zhàn)
IP,TCP 和 HTTP
動畫解釋
響應(yīng)式 Android 應(yīng)用
初識 TextKit
客戶端
View-Layer 協(xié)作
回到 Mac
Android
Core Image 介紹
自定義 Formatters
Scene Kit
調(diào)試
項(xiàng)目介紹
Swift 的強(qiáng)大之處
測試并發(fā)程序
Android 通知中心
調(diào)試:案例學(xué)習(xí)
從 UIKit 到 AppKit
iOS 7 : 隱藏技巧和變通之道
安全
底層并發(fā) API
消息傳遞機(jī)制
更輕量的 View Controllers
用 SQLite 和 FMDB 替代 Core Data
字符串解析
終身學(xué)習(xí)的一代人
視頻
Playground 快速原型制作
Omni 內(nèi)部
同步數(shù)據(jù)
設(shè)計(jì)優(yōu)雅的移動游戲
繪制像素到屏幕上
相機(jī)與照片
音頻 API 一覽
交互式動畫
常見的后臺實(shí)踐
糟糕的測試
避免濫用單例
數(shù)據(jù)模型和模型對象
Core Data
字符串本地化
View Controller 轉(zhuǎn)場
照片框架
響應(yīng)式視圖
Square Register 中的擴(kuò)張
DTrace
基礎(chǔ)集合類
視頻工具箱和硬件加速
字符串渲染
讓東西變得不那么糟
游戲中的多點(diǎn)互聯(lián)
iCloud 和 Core Data
Views
虛擬音域 - 聲音設(shè)計(jì)的藝術(shù)
導(dǎo)航應(yīng)用
線程安全類的設(shè)計(jì)
置換測試: Mock, Stub 和其他
Build 工具
KVC 和 KVO
Core Image 和視頻
Android Intents
在 iOS 上捕獲視頻
四軸無人機(jī)項(xiàng)目
Mach-O 可執(zhí)行文件
UI 測試
值對象
活動追蹤
依賴注入
Swift
項(xiàng)目管理
整潔的 Table View 代碼
Swift 方法的多面性
為什么今天安全仍然重要
Core Data 概述
Foundation
Swift 的函數(shù)式 API
iOS 7 的多任務(wù)
自定義 Collection View 布局
測試 View Controllers
訪談
收據(jù)驗(yàn)證
數(shù)據(jù)同步
自定義 ViewController 容器轉(zhuǎn)場
游戲
調(diào)試核對清單
View Controller 容器
學(xué)無止境
XCTest 測試實(shí)戰(zhàn)
iOS 7
Layer 中自定義屬性的動畫
第一期-更輕量的 View Controllers
精通 iCloud 文檔存儲
代碼審查的藝術(shù):Dropbox 的故事
GPU 加速下的圖像視覺
Artsy
照片擴(kuò)展
理解 Scroll Views
使用 VIPER 構(gòu)建 iOS 應(yīng)用
Android 中的 SQLite 數(shù)據(jù)庫支持
Fetch 請求
導(dǎo)入大數(shù)據(jù)集
iOS 開發(fā)者的 Android 第一課
iOS 上的相機(jī)捕捉
語言標(biāo)簽
同步案例學(xué)習(xí)
依賴注入和注解,為什么 Java 比你想象的要好
編譯器
基于 OpenCV 的人臉識別
玩轉(zhuǎn)字符串
相機(jī)工作原理
Build 過程

iCloud 和 Core Data

當(dāng)喬布斯第一次在蘋果全球開發(fā)大會上介紹 iCloud 的時(shí)候,他將無縫同步的功能描述的太過完美,以至于讓人懷疑其是否真的能實(shí)現(xiàn)。但當(dāng)你在 iOS 5iOS 6 系統(tǒng)中嘗試使用 iCloud Core Data 同步的時(shí)候你會對其真實(shí)情況了如指掌。

庫風(fēng)格應(yīng)用(譯者注:"盒子類型",比如 iPhoto )的同步中的問題導(dǎo)致很多開發(fā)者放棄支持 iCloud,而選擇一些其他的方案比如 Simperium,TICoreDataSyncWasabiSync。

2013年初,在蘋果公司不透明及充滿 bug 的 iCloud Core Data 同步實(shí)現(xiàn)中掙扎多年后,開發(fā)者終于公開批判了這項(xiàng)服務(wù)的重大缺陷并將這個話題推上了風(fēng)口浪尖。 最終被 Ellis Hamburger 在一篇尖銳文章提出。

WWDC

蘋果也注意到了,很明顯這些事情必須改變。在 WWDC 2013,Nick Gillett 宣布 Core Data 團(tuán)隊(duì)花了一年時(shí)間專注于在 iOS 7 中解決一些 iCloud 最令人挫敗的漏洞,承諾大幅改善問題并且讓開發(fā)者更簡單的使用?!拔覀兠黠@減少了開發(fā)者所需要編寫的復(fù)雜代碼的數(shù)量。” Nick Gillett在 [“What’s New in Core Data and iCloud”] 舞臺上講到。 在 iOS 7 中,Apple 專注于 iCloud 的速度,可靠性,和性能,事實(shí)上這卓有成效。

讓我們看看具體有哪些改變,以及如何在 iOS 7 應(yīng)用程序?qū)崿F(xiàn) Core Data。

設(shè)置

要設(shè)置一個 iCloud Core Data 應(yīng)用,你首先需要在你的應(yīng)用中請求 iCloud 的訪問權(quán)限,讓你的應(yīng)用程序可以讀寫一個或多個開放性容器 (ubiquity containers),在 Xcode 5中你可以在你應(yīng)用 target 的 “Capabilities” 選項(xiàng)卡中輕易完成著這一切。

在開放性容器內(nèi)部,Core Data Framework 將會存儲所有的事務(wù)日志 -- 記錄你的所有持久化的存儲 -- 為了跨設(shè)備同步數(shù)據(jù)做準(zhǔn)備。 Core Data 使用了一個被稱為多源復(fù)制(multi-master replication)的技術(shù)來同步 iOS 和 Macs 之間的數(shù)據(jù)??沙志没鎯Φ臄?shù)據(jù)存在了每個設(shè)備的 CoreDataUbiquitySupport 文件夾里,你可以在應(yīng)用沙盒中找到他。當(dāng)用戶修改了 iCloud accounts,Core Data framework 會管理多個賬戶,而并不需要你自己去監(jiān)聽NSUbiquityIdentityDidChangeNotification。

每一個事務(wù)日志都是一個plist文件,負(fù)責(zé)實(shí)體的跟蹤插入,刪除以及更新。這些日志會自動被系統(tǒng)按照一定基準(zhǔn)合并。

在你設(shè)置iCloud的持久化存儲的時(shí)候,調(diào)用addPersistentStoreWithType:configuration:URL:options:error:或者 migratePersistentStore:toURL:options:withType:error:的時(shí)候注意需要設(shè)置一些選項(xiàng):

  • NSPersistentStoreUbiquitousContentNameKey (NSString)
    給 iCloud 存儲空間指定一個名字(例如 @“MyAppStore”)

  • NSPersistentStoreUbiquitousContentURLKey (NSString, iOS 7 中可選) 給事務(wù)日志指定一個二級目錄(例如 @"Logs")

  • NSPersistentStoreUbiquitousPeerTokenOption (NSString, 可選)
    為每個程序設(shè)置一個鹽,為了讓不同應(yīng)用可以在同一個集成 iCloud 的設(shè)備中分享 Core Data 數(shù)據(jù) (比如@"d70548e8a24c11e3bbec425861b86ab6")

  • NSPersistentStoreRemoveUbiquitousMetadataOption (NSNumber (Boolean), 可選) 指定程序是否需要備份或遷移 iCloud 的元數(shù)據(jù)(例如 @YES)

  • NSPersistentStoreUbiquitousContainerIdentifierKey (NSString)
    指定一個容器,如果你的應(yīng)用有多個容器定義在 entitlements 中(例如 @"com.company.MyApp.anothercontainer")

  • NSPersistentStoreRebuildFromUbiquitousContentOption (NSNumber (Boolean), 可選) 告訴 Core Data 抹除本地存儲數(shù)據(jù)并且用 iCoud 重建數(shù)據(jù)(例如 @YES)

只支持 iOS 7 的應(yīng)用的唯一必填選項(xiàng)是 ContentNameKey,它是為了讓 Core Data 知道把日志和元數(shù)據(jù)放在哪里。在 iOS 7 中,你傳入 NSPersistentStoreUbiquitousContentNameKey 的字符串值不應(yīng)該包含'.'。 如果你的應(yīng)用已經(jīng)使用 Core Data 去存儲持久化數(shù)據(jù),但是沒有實(shí)現(xiàn) iCloud 同步,你只需要簡單加入 content name key 就能將存儲轉(zhuǎn)為可以使用 iCloud 的狀態(tài),而無需關(guān)注有沒有活躍的 iCloud 賬戶。

為你的應(yīng)用設(shè)置一個管理對象上下文簡單到只需要實(shí)例化一個 NSManagedObjectContext 并連同一個合并策略一并告訴你的持久化存儲。蘋果建議使用 NSMergeByPropertyObjectTrumpMergePolicy 作為合并策略,它會合并沖突,并給予內(nèi)存中的變化的數(shù)據(jù)相較于磁盤數(shù)據(jù)更高的優(yōu)先級。

雖然 Apple 還沒有發(fā)布官方的 iOS7 中 iCloud Core Data 的示例代碼,但是 Apple 的 Core Data 團(tuán)隊(duì)中的一個工程師在開發(fā)者論壇上提供了這個模板。我們稍微修改讓它更清晰:

#pragma mark - Notification Observers
- (void)registerForiCloudNotifications {
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];

    [notificationCenter addObserver:self 
                           selector:@selector(storesWillChange:) 
                               name:NSPersistentStoreCoordinatorStoresWillChangeNotification 
                             object:self.persistentStoreCoordinator];

    [notificationCenter addObserver:self 
                           selector:@selector(storesDidChange:) 
                               name:NSPersistentStoreCoordinatorStoresDidChangeNotification 
                             object:self.persistentStoreCoordinator];

    [notificationCenter addObserver:self 
                           selector:@selector(persistentStoreDidImportUbiquitousContentChanges:) 
                               name:NSPersistentStoreDidImportUbiquitousContentChangesNotification 
                             object:self.persistentStoreCoordinator];
}

# pragma mark - iCloud Support

/// 在 -addPersistentStore: 使用這些配置
- (NSDictionary *)iCloudPersistentStoreOptions {
    return @{NSPersistentStoreUbiquitousContentNameKey: @"MyAppStore"};
}

- (void) persistentStoreDidImportUbiquitousContentChanges:(NSNotification *)notification {
    NSManagedObjectContext *context = self.managedObjectContext;

    [context performBlock:^{
        [context mergeChangesFromContextDidSaveNotification:changeNotification];
    }];
}

- (void)storesWillChange:(NSNotification *)notification {
    NSManagedObjectContext *context = self.managedObjectContext;

    [context performBlockAndWait:^{
        NSError *error;

        if ([context hasChanges]) {
            BOOL success = [context save:&error];

            if (!success && error) {
                // 執(zhí)行錯誤處理
                NSLog(@"%@",[error localizedDescription]);
            }
        }

        [context reset];
    }];

    // 刷新界面
}

- (void)storesDidChange:(NSNotification *)notification {
    // 刷新界面
}

異步持久化設(shè)置

在 iOS 7 中,使用 iCloud 選項(xiàng)來調(diào)用 addPersistentStoreWithType:configuration:URL:options:error: 幾乎可以瞬間返回存儲對象。1 能做到這樣是因?yàn)樗紫仍O(shè)置了一個內(nèi)部‘回滾’存儲,利用本地存儲作為一個占位符,同時(shí)由事務(wù)日志和元數(shù)據(jù)來異步地構(gòu)建 iCloud 存儲。當(dāng)回滾存儲有變化時(shí),這些變化將在 iCloud 存儲被添加到 coordinator 時(shí)合并至其中。在完成回滾存儲的設(shè)置后,控制臺將會打印Using local storage: 1 ,當(dāng) iCloud 完全設(shè)置完后,你會看到 Using local storage: 0。 這句話的意思是 iCloud 存儲已經(jīng)啟用,此后你可以通過監(jiān)聽NSPersistentStoreDidImportUbiquitousContentChangesNotification看到來自 iCloud 的內(nèi)容。

如果你的應(yīng)用關(guān)注在不同存儲間的遷移,那么你需要監(jiān)聽 NSPersistentStoreCoordinatorStoresWillChangeNotification 和/或NSPersistentStoreCoordinatorStoresDidChangeNotification(將這些通知關(guān)聯(lián)到你的 coordinator,這樣就可以過濾其他和你無關(guān)的通知) 并且在 userInfo 中檢查 NSPersistentStoreUbiquitousTransitionTypeKey 的值, 這個數(shù)值是一個對應(yīng) NSPersistentStoreUbiquitousTransitionType 枚舉類型的 NSNumber,在遷移已經(jīng)發(fā)生時(shí),這個值是NSPersistentStoreUbiquitousTransitionTypeInitialImportCompleted

邊緣情況

混淆 (Churn)

在 iOS 5 和 iOS 6 中測試 iCloud 時(shí)最嚴(yán)重的一個問題是重度用戶的賬號會遇到一種“混淆”的狀態(tài),導(dǎo)致無法使用。同步將完全停止,甚至刪除開放性數(shù)據(jù)也無法使其正常工作。在 Lickability,我們親切地稱為這種狀態(tài)“f \ \ \ * ing bucket?!?/p>

在 iOS 7 中,系統(tǒng)提供了一個方法來真正移除全部的開放性存儲內(nèi)容: +removeUbiquitousContentAndPersistentStoreAtURL:options:error:,這個方法對測試很有幫助,甚至在你應(yīng)用中,當(dāng)你用戶進(jìn)入了一個不正常的狀態(tài)時(shí),他們可以通過這個方法刪除所有數(shù)據(jù),并重新來過。不過,需要指出的是:首先,這種方法是同步的。甚至在做網(wǎng)絡(luò)操作的時(shí)候它也是同步的,因此它會花很長時(shí)間,并且在完成前也不會返回。第二,絕對不能在有持久性存儲 coordinators 活躍時(shí)執(zhí)行此操作。這樣會造成很嚴(yán)重的問題,你的應(yīng)用程序可能進(jìn)入一個不可恢復(fù)的狀態(tài),而且官方指導(dǎo)指出所有活躍的持久性存儲 coordinators 都應(yīng)在使用這個方法前完全銷毀收回。

賬戶修改

iOS 5 系統(tǒng)中,用戶在切換 iCloud 賬戶或者禁用賬戶時(shí),NSPersistentStoreCoordinator 中的數(shù)據(jù)會在應(yīng)用無法知曉的情況下完全消失。事實(shí)上檢查一個賬號是否變更了的唯一的方法是調(diào)用 NSFileManager 中的 URLForUbiquityContainerIdentifier,這個方法可以創(chuàng)建一個開放性容器文件夾,而且需要數(shù)秒返回。在 iOS 6,這種情況隨著引進(jìn) ubiquityIdentityToken 和相應(yīng)的NSUbiquityIdentityDidChangeNotification 之后得到改善。因?yàn)樵?ubiquity id 變化的時(shí)候會發(fā)送通知,這就可以對應(yīng)用賬戶的變更進(jìn)行有效的確認(rèn)并及時(shí)的發(fā)出提示。

然而,iOS 7 中這種轉(zhuǎn)換的情況就變得更加簡單,賬戶的切換是由 Core Data 框架來處理的,因此只要你的程序能夠正常響應(yīng) NSPersistentStoreCoordinatorStoresWillChangeNotificationNSPersistentStoreCoordinatorStoresDidChangeNotification 便可以在切換賬戶的時(shí)候流暢的更換信息。檢查 userInfo 的字典中 NSPersistentStoreUbiquitousTransitionType 鍵將提供更多關(guān)于遷移的類型的細(xì)節(jié)。

在應(yīng)用沙箱中框架會為每個賬戶管理各自獨(dú)立的持久化存儲,所以這就意味著如果用戶回到之前的賬戶,其數(shù)據(jù)會和之前離開時(shí)一樣,仍然可用。Core Data 現(xiàn)在也會在磁盤空間不足時(shí)管理對這些文件進(jìn)行的清理工作。

iCloud 的啟用與停用

在 iOS 7 中應(yīng)用實(shí)現(xiàn)用一個開關(guān)用來切換啟用關(guān)閉 iCloud 變的非常容易,雖然對大部分應(yīng)用來說這個功能不是很需要,因?yàn)樵趧?chuàng)建 NSPersistentStore 時(shí)候如果加入 iCloud 選項(xiàng),那么 API 現(xiàn)在將自動建立一個獨(dú)立的文件結(jié)構(gòu),這意味著本地存儲和 iCloud 存儲共用相同的存儲 URL 和其他很多設(shè)置。這個選項(xiàng)將把 ubiquitous 元數(shù)據(jù)和存儲本身進(jìn)行分離,并專門為遷移或者復(fù)制的場景進(jìn)行了特殊設(shè)計(jì)。下面是一個示例:

- (void)migrateiCloudStoreToLocalStore {
    // 假設(shè)你只有一個存儲
    NSPersistentStore *store = [[_coordinator persistentStores] firstObject]; 

    NSMutableDictionary *localStoreOptions = [[self storeOptions] mutableCopy];
    [localStoreOptions setObject:@YES forKey:NSPersistentStoreRemoveUbiquitousMetadataOption];

    NSPersistentStore *newStore =  [_coordinator migratePersistentStore:store 
                                                                  toURL:[self storeURL] 
                                                                options:localStoreOptions 
                                                               withType:NSSQLiteStoreType error:nil];

    [self reloadStore:newStore];
}

- (void)reloadStore:(NSPersistentStore *)store {
    if (store) {
        [_coordinator removePersistentStore:store error:nil];
    }

    [_coordinator addPersistentStoreWithType:NSSQLiteStoreType 
                               configuration:nil 
                                         URL:[self storeURL] 
                                     options:[self storeOptions] 
                                       error:nil];
}

切換一個本地存儲到 iCloud 存儲是一個非常容易的事情,簡單到只需啟用 iCloud 選項(xiàng),并且把擁有相同選項(xiàng)的可持久存儲加入到 coordinator 中。

外部文件的引用

外部文件的應(yīng)用是一個在 iOS 5 中加入的 Core Data 新特性,允許大尺寸的二進(jìn)制自動存儲在 SQLite 數(shù)據(jù)庫之外的文件系統(tǒng)中。 在我們測試中,當(dāng)發(fā)生改變時(shí),iCloud 并不知道如何解決依賴關(guān)系并會拋出異常。如果你計(jì)劃使用 iCloud 同步 ,可以考慮在 iCloud entities 中取消這個選擇:

http://wiki.jikexueyuan.com/project/objc/images/10-6.png" alt="" />

Model 版本

如果你計(jì)劃使用 iCloud,存儲的內(nèi)容只能在未來兼容自動輕量級遷移, 這意味著 Core Data 需要能推斷出映射,你也不能提供自己的映射模型。在未來只有對 Model 的簡單改變,比如添加和重命名屬性,才能被支持。在考慮是否使用 Core Data 同步時(shí),一定要考慮到你的 app 的 Model 在未來版本中改變的情況。

合并沖突

在任何同步系統(tǒng)中,服務(wù)器和客戶端之前的文件沖突是不可避免的。不同于 iCloud Data 文檔同步的 APIs, iCloud 的 Core Data 整合并沒有明確允許處理本地存儲和事務(wù)日志之間的沖突。這其實(shí)是因?yàn)?Core Data 已經(jīng)支持通過實(shí)現(xiàn) NSMergePolicy 的子類來自定義策合并策略。 如果你要處理沖突,創(chuàng)建 NSMergePolicy 的子類并且覆蓋 resolveConflicts:error: 來決定在沖突發(fā)生的時(shí)候做什么。然后在你的 NSManagedObjectContext 子類中,讓mergePolicy 方法返回一個你自定義的策略的實(shí)例。

界面更新

很多庫風(fēng)格應(yīng)用同時(shí)顯示集合對象和一個對象的詳細(xì)信息。 視圖是由 NSFetchedResultsController 實(shí)例自動從網(wǎng)絡(luò)更新 Core Data 的數(shù)據(jù)然后刷新。然而,您應(yīng)該確保每一個詳細(xì)視圖正確監(jiān)聽變化對象并使自己保持最新。如果你不這樣做, 將有顯示陳舊的數(shù)據(jù)的風(fēng)險(xiǎn),或者更糟,你將覆蓋其他設(shè)備修改的數(shù)據(jù)。

測試

本地網(wǎng)絡(luò)和因特網(wǎng)同步

iCloud 守護(hù)進(jìn)程將使用本地網(wǎng)絡(luò)或使用因特網(wǎng)這兩種方式中的其中一種,來進(jìn)行跨設(shè)備的數(shù)據(jù)同步。守護(hù)進(jìn)程檢測到兩個設(shè)備時(shí),也被稱為對等網(wǎng)絡(luò),在同一個局域網(wǎng),將在內(nèi)網(wǎng)快速傳輸。然而,如果在不同的網(wǎng)絡(luò),該系統(tǒng)將傳輸回滾事務(wù)日志。這很重要,你必須在開發(fā)中對兩種情況進(jìn)行大量的測試,以確保您的應(yīng)用程序正常運(yùn)作。在這兩種場景中,從備份存儲同步更改或過渡到 iCloud 有時(shí)需要比預(yù)期更長的時(shí)間,所以如果有什么不工作,嘗試給它點(diǎn)時(shí)間。

模擬器中使用 iCloud

在 iOS 7 中最有用的更新就是 iCloud 終于可以在模擬器中使用。在以往的版本中,你只能在設(shè)備中測試,這個限制使監(jiān)聽開發(fā)的同步進(jìn)程有點(diǎn)困難?,F(xiàn)在你甚至可以在你的 Mac 和模擬器中進(jìn)行數(shù)據(jù)同步。

在 Xcode 5 新增的 iCloud 調(diào)試儀表中,你可以看到在你的應(yīng)用程序的開放性存儲中的文件,以及檢查它們的文件傳輸狀態(tài),比如 "Current", "Excluded", 和 "Stored in Cloud" 等。 對于更底層的調(diào)試,可以把 -com.apple.coredata.ubiquity.logLevel 3 加入到啟動參數(shù)或者設(shè)置成用戶默認(rèn),以啟用詳細(xì)日志。還可以考慮在 iOS 中安裝 iCloud 存儲調(diào)試日志配置文件 以及新的 ubcontrol 命令行工具提供高質(zhì)量錯誤報(bào)告到Apple 。你可以在你的設(shè)備連入 iTunes 并同步后在 ~/Library/Logs/CrashReporter/MobileDevice/device-name/DiagnosticLogs 中獲取這些工具生成的日志。

然而,iCloud Core Data 并不完全支持模擬器。在用實(shí)際設(shè)備和模擬器測試傳輸時(shí),似乎模擬器的 iCloud Core Data 只上傳更改,卻從不把它們抓取下來。雖然比起分別使用多個不同測試設(shè)備來說,確實(shí)進(jìn)步和方便了很多,但是 iOS 模擬器上的 iCloud Core Data 支持絕對還沒有完全成熟。

繼續(xù)改進(jìn)

因?yàn)?iOS 7 中 APIs 和功能得到了極大的改善,那些在 iOS 5 和 iOS 6 上分發(fā)的帶有 iCloud Core Data 的應(yīng)用的命運(yùn)就顯得撲朔迷離了。 由于從 API 的角度來看它們完全不同(當(dāng)然我們從功能角度也驗(yàn)證了這一點(diǎn)),Apple 的建議對于那些需要傳統(tǒng)同步的應(yīng)用來說并不那么友好。Apple 清楚地開發(fā)者論壇 上建議,絕對不要在 iOS 7 和之前的設(shè)備同步之間同步數(shù)據(jù)。

事實(shí)上,“任何時(shí)候你都不應(yīng)該在 iOS 7 與 iOS 6 同步。iOS 6 將持續(xù)造成那些已經(jīng)在 iOS 7 上修正了的 bug,這樣做將會會污染 iCloud 賬戶?!?保證這種分離的最簡單的方法是簡單地改變你存儲中的 NSPersistentStoreUbiquitousContentNameKey,遵循規(guī)范進(jìn)行命名。這樣保證從舊版本數(shù)據(jù)同步的方法是孤立的,并允許開發(fā)人員從老舊的實(shí)現(xiàn)中完全脫身。

發(fā)布

發(fā)布一個 iCloud Core Data 應(yīng)用仍舊有很大的風(fēng)險(xiǎn),你需要對所有的環(huán)節(jié)進(jìn)行測試:賬戶轉(zhuǎn)換,iCloud 存儲空間耗盡,多種設(shè)備,Model 的升級,以及設(shè)備恢復(fù)等。盡管 iCloud 調(diào)試儀表和 developer.icloud.com 對這些有所幫助,但依靠一個你完全無法控制的服務(wù)來發(fā)布一個應(yīng)用仍然需要那種縱身一躍入深淵的信念。

正如 Brent Simmon 提到的,發(fā)布任意一種 iCloud Syncing 應(yīng)用都會有限制,所以需要事先了解一下成本。像 Day One1Password 這樣的程序,會讓使用者選擇用 iCloud 還是 Dropbox 來同步他們的數(shù)據(jù)。對于很多使用者來說,沒什么可以比一個獨(dú)立的賬戶更加簡易,但是一部分動手能力強(qiáng)的人喜歡更好的更全面的控制他們的數(shù)據(jù)。對于開發(fā)者而言,維持這種完全不同的數(shù)據(jù)庫同步系統(tǒng)在開發(fā)和測試的過程當(dāng)中是十分繁瑣和超負(fù)荷的。

Bugs

一旦你測試并且發(fā)布了你的 iCloud Core Data 應(yīng)用,你很可能會遇到很多框架里的 bug,最好的辦法是反饋這些 bug 的詳細(xì)信息到 Apple,其中需要包含以下信息:

  1. 完整的重現(xiàn)步驟
  2. 安裝了 iCloud 調(diào)試配置并將 iCloud 調(diào)試日志輸出級別調(diào)為 3 的終端輸出
  3. 打包為 zip 的完整的開放性存儲內(nèi)容

結(jié)論

在 iOS 5 和 6 中 iCloud Core Data 根本就沒法用這件事已經(jīng)是不是一個秘密, Apple 的程序員自己都承認(rèn)“在 iOS 5 和 6 中使用 Core Data + iCloud 時(shí),存在重大的穩(wěn)定性和長期可靠性的問題,要使用它的話請一定一定一定把應(yīng)用設(shè)為 iOS 7 only“。一些高端的開發(fā)者,比如 Agile Tortoise 以及 Realmac Software,現(xiàn)在已經(jīng)信任 iCloud Core Data,并把它集成到了他們的應(yīng)用中。因?yàn)橛兄浞值?a rel="nofollow" >考量和測試,你也應(yīng)該這么做了。

特別感謝 Andrew Harrison, Greg Pierce, and Paul Bruneau 對這篇文章的幫助


  1. 在之前的 OS 版本中,這個方法直到 iCloud 數(shù)據(jù)下載并合并到持久化存儲中前是不會返回的。這將造成大幅延遲,并意味著任何對這個方法的調(diào)用需要被派發(fā)到一個后臺的隊(duì)列中去。值得慶幸的是現(xiàn)在已經(jīng)不再需要這么做了。