作者:坐隐在线
iOS中实现SQLite数据库云存储(iCloud)大概需要三步:
一、设置项目支持iCloud
二、persistentStoreCoordinat or中设置对iCloud存取
三、设置iCloud数据变化时的一个通知监听,以便在数据变化时同步本地用户界面。
下面进行看图说话:
1,新建一个Master-Detail iOS项目。
2,设置项目名称为TestiCloud,勾选Use Core Data,项目将自动创建一个SQLite数据库,便于测试。然后一路下一步完成项目创建。
3,登录苹果的开发者中心:developer.apple.com,点击iOS Provisioning Portal,使项目支持iCloud
4,建立一个新的App ID,如果是使原有项目支持iCloud,则跳过第4、5步。
5,填写描述及Bundle ID,这里是TestiCloud和net.zuoyin.TestiCloud
6,创建成功后列表中将出现新建的App ID(如果是原来的项目则在此直接修改),点击configure
7、勾选Enable for iCloud,弹出一个对话框,提示项目需重建provisioning,点击OK
8,点击左栏的Provisioning,然后点New Profile(如果是老项目,删掉原来的provisioning,重建)
9,建立provisioning,注意App ID的选择
10,下载新建的provisioning,拖到Organizer中,然后打开新建项目的Code signing,设置为相应的provisioning.
11,打开targets的Summary设置面板,向下拉,找到Entitlements,勾选Entitlements File(你会发现勾选后项目导航栏会增加一个名为TestiCloud.entitlements的文件),然后勾选Enable iCloud,key-Value Store程序中没用,所以不管这个(这是另外两种使用iCloud的方式中的一种,Key-Value Store类似于 NSUserDefaults的保存键值对,另一种是使用NSDocument管理文档,使用方法可查看Apple文档)。下面的Ubiquity Containners对SQLite很重要,点加号会自动增加一个Container,够测试用了。
12,现在如果没有出现错误,iCloud应该可用了,先在YTAppDelegat.m中增加一个测试iCloud的方法:
#define UBIQUOUTY_CONTAINER_IDENTITY @"TEAM_ID.net.zuoyin.TestiCloud"
@interface YTAppDelegate()
- (BOOL)isiCloudAvailable;
@end
- (BOOL)isiCloudAvailable
{
NSURL *dbURL=[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:UBIQUOUTY_CONTAINER_IDENTITY];
if (dbURL)
{
return YES;
}
else return NO;
}
注意常量定义中的TEAM_ID是形如“179DVMTAP1”这样的字符,可在Provisioning Portal中查找。
然后在application:didFinishLauchingWithOpt ions方法中加入两行代码:
if (self.isiCloudAvailable) NSLog(@"Good job!");
else NSLog(@"Sorry,You must work harder...");
进行测试,修改后的代码是这样的。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOp tions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
UINavigationController *masterNavigationControll er = splitViewController.viewControllers[0];
YTMasterViewController *controller = (YTMasterViewController *)masterNavigationControll er.topViewController;
controller.managedObjectContext = self.managedObjectContext;
} else {
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
YTMasterViewController *controller = (YTMasterViewController *)navigationController.topViewController;
controller.managedObjectContext = self.managedObjectContext;
}
if (self.isiCloudAvailable) NSLog(@"Good job!");
else NSLog(@"Sorry,You must have made some mistakes...");
return YES;
}
确定程序不会产生诸如使显示器爆炸等恶劣后果,运行程序,输出如下图,电脑夸你干得好,说明前面进行的设置没有问题^_^,iCloud可正常使用。现在完成了第一步。
下面进行第二步:修改persistentStoreCoordinat or方法以增加对iCloud的存取,修改部分我已经加红了。
- (NSPersistentStoreCoordin ator *)persistentStoreCoordinat or
{
if (_persistentStoreCoordinat or != nil) {
return _persistentStoreCoordinat or;
}
NSDictionary *optinotallow=nil;
if ([self isiCloudAvailable])
{
NSURL *dbURL=[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:UBIQUOUTY_CONTAINER_IDENTITY];
optinotallow=[NSDictionary dictionaryWithObjectsAndKeys:@"net.zuoyin.TestiCloud.SQLite",NSPersistentStoreUbiquitousContentNameKey,dbURL,NSPersistentStoreUbiquitousContentURLKey, nil];
}
NSURL *storeURL = [[self applicationDocumentsDire ctory] URLByAppendingPathCompon ent:@"TestiCloud.sqlite"];
NSError *error = nil;
_persistentStoreCoordinat or = [[NSPersistentStoreCoordin ator alloc] initWithManagedObjectMod el:[self managedObjectModel]];
if (![_persistentStoreCoordinat or addPersistentStoreWithTy pe:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinat or;
}
注意:if (![_persistentStoreCoordinat or addPersistentStoreWithTy pe:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) 新定义的options变量取代了原来的nil。
下面进行第三步:设置iCloud数据变化监听,修改
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordin ator *coordinator = [self persistentStoreCoordinat or];
if (coordinator != nil) {
NSManagedObjectContext *managedObjectContext = [[NSManagedObjectContext alloc]
initWithConcurrencyType:NSMainQueueConcurrencyTy pe];
[managedObjectContext performBlockAndWait:^(void){
[managedObjectContext setPersistentStoreCoordi nator:coordinator];
if([self isiCloudAvailable])
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(iCloudDataDidChange)
name:NSPersistentStoreDidImportUbiquitousContentChangesNotification
object:coordinator];
}
}];
_managedObjectCnotallow=managedObjectContext;
}
return _managedObjectContext;
}
增加相应的调用方法:
//Very very bad code!
- (void)iCloudDataDidChange{
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
YTMasterViewController *controller = (YTMasterViewController *)navigationController.topViewController;
controller.fetchedResultsController=nil;
[controller fetchedResultsController];
[controller.tableView reloadData];
}
iClo
udDataDidChange方法只是为了测试,千万别在程序中直接这样做(iPad这样更新tableView数据会直接闪退
)
对了,模拟机上不能进行iCloud测试,所以必须用两台实际的设备进行测试。
运行程序,先在iPad上点击加号,会增加数据。
等了大约有一分钟,哇!手机上数据更新了,My iCloud!但是怎么只有两行呢?iPad上填加了四行啊?程序问题?网络问题?iCloud问题?还没搞明白。
抽了根烟,继续等,还是那样。算了,都删掉,再加四行。这次在iPhone上先加:
这次数据对了(iPad闪退了四次,看来数据是一条一条从iCloud更新回来的
)
小结:
SQLite(Core Data)进行云存储还是挺简单的,没增加多少代码。当然这只是个测试,具体实现上还会有一些问题,比如我还发现这个测试启动时非常慢(看来启动就测试云是否可用不是好办法)。