iCloud开发实践

本文介绍了iCloud在iOS开发中的应用,包括Key-value同步、文档数据同步、本地数据库(CoreData)同步以及CloudKit的使用。通过实例展示了如何设置iCloud服务、使用Key-value进行数据同步、使用文档数据同步服务以及利用CloudKit管理数据库。文中还提到,从iOS 10起,Apple推荐使用CloudKit代替CoreData进行同步。
摘要由CSDN通过智能技术生成

写在前面

最近在一直在研究iCloud开发相关的东西,觉得是有必要写篇总结来整理一下近段时间的一些学习成果。之前一直听说iCloud服务不友好也不完善,开发难度也相对较大,其实个人觉得貌似也没说错,iCloud在客户端提供的框架相比于其他的功能框架来说,他是被分散到各个框架中,要使用它必须要了解各个部分的功能及使用场合,这样就增加了学习的成本。同时,框架的设计也比较松散,特别是文档同步,虽然提供了灵活功能强大的框架,但是要理清楚还是需要时间去学习和实践。

为了让大家少走弯路,我将iCloud划分了几大功能模块,下面会逐个地讲述每个模块的一些基本使用,同时配备例子进行说明:

准备工作

想要使用iCloud服务我们必须要有一个苹果的开发者账号(99$个人或者企业都可以),然后需要为项目进行一些配置:

  1. 在Xcode中点击项目目录结构的根节点进入项目设置
  2. 在Capabilities页签中找到iCloud一项,然后将对应该项的开关设置为开启状态。
  3. 在iCloud一栏下的有Services和Containers两个小栏目,其中Services中有三个选项,其对应说明如下:
名称 说明
Key-value storage 键值对的存储服务,用于一些简单的数据存储
iCloud Documents 文档存储服务,用于将文件保存到iCloud中
CloudKit 云端数据库服务

这三种服务会在后续章节为大家详细进行讲解。然后就是Container这一栏,顾名思义,其实可以简单认为他是用于存放数据的地方,因为每个应用所存放的数据应该是独立的同时也具有沙箱的限制,所以iOS为每个应用开辟了一个独立的空间来存放在iCloud的文件或数据,同时也方便从iCloud上同步数据到这个地方。默认情况下,一旦开启iCloud服务,就会创建一个默认的容器,其命名为iCloud + BundleID。如果你不想要使用默认的容器又或者想跟自己开发的其他App共享文件数据,则可以选择Specify custom containers选项,然后在容器列表中选择一个指定的容器,或者点击+号创建一个新的容器。

配置完成后,效果如图所示:

开启iCloud服务

注意:iCloud下面的Steps必须都打上勾才表示正常启用服务,否则需要根据提示检查你的苹果开发者账号中的一些应用设置。

在正式开始前还有一个事情要说清楚的,这里仅仅讨论的是使用iCloud作为登录账号的app,如果你的app有自己的用户系统,那么你还需要将同步的数据进行标识(例如加个系统用户标识来确定那份数据是哪个用户的),然后根据标识进行数据合并。好了,下面可以开始讲述一些具体开发过程(敲代码时间到了~)

Key-value同步

该种方式一般用于同步少量数据或者进行一些配置性质的数据同步。其使用也比较简单,iOS提供了一个NSUbiquitousKeyValueStore的类型来实现相关的操作。它的使用跟NSUserDefaults类似。主要提供以下的功能:

名称 说明
defaultStore 返回NSUbiquitousKeyValueStore对象,用于Key-value的存取操作
objectForKey: 获取指定key的值
setObject:forKey: 设置指定key的值
removeObjectForKey: 移除指定键值
stringForKey: 获取指定key保存的字符串,如果指定key不存在或者对应key保存的值不是NSString类型时则返回nil
setString:forKey: 为指定key设置一个字符串
arrayForKey: 获取指定key保存的数组,如果指定key不存在或者对应key保存的值不是NSArray类型时则返回nil
setArray:forKey: 为指定key设置一个数组对象
dictionaryForKey: 获取指定key保存的字典,如果指定key不存在或者对应key保存的值不是NSDictionary类型时则返回nil
setDictionary:forKey: 为指定key设置一个字典对象
dataForKey: 获取指定key保存的二进制数组,如果指定key不存在或者对应key保存的值不是NSData类型时则返回nil
setData:forKey: 为指定key设置一个二进制数组
longLongForKey: 获取指定key保存的64位整型值,如果指定key不存在或者对应key保存的值不包含数值时则返回0
setLongLong:forKey: 为指定key设置一个64位整型值
doubleForKey: 获取指定key保存的浮点数值,如果指定key不存在或者对应key保存的值不包含数值时则返回0
setDouble:forKey: 为指定key设置一个浮点数值
boolForKey: 获取指定key保存的布尔值,如果指定key不存在则返回NO
setBool:forKey: 为指定key设置一个布尔值
synchronize 同步数据,将在内存中的数据同步到磁盘中,并上传至iCloud
dictionaryRepresentation 该属性会返回载入到内存中保存的key-value字典,如果想要最新的数据则需要先调用synchronize方法

下面我们来举个例子,看看如何使用NSUbiquitousKeyValueStore进行数据同步。

首先,我们在界面中拖入两个按钮,一个用于设置数据,一个用于获取数据,如图所示:

Key-value Storage演示界面

然后在VC中声明一个NSUbiquitousKeyValueStore类型的属性,并且把两个按钮与VC的按钮点击事件进行关联,其中VC代码如下:

@interface KeyValueViewController ()

// Key-value同步数据存储对象
@property (nonatomic, strong) NSUbiquitousKeyValueStore *keyValueStore;

@end

@implementation KeyValueViewController

- (IBAction)setValueButtonClickedHandler:(id)sender
{
   
    // 设置值按钮点击事件
}

- (IBAction)getValueButtonClickedHandler:(id)sender
{
   
    // 获取值按钮点击事件
}

然后在viewDidLoad方法中对keyValueStore进行初始化:

- (void)viewDidLoad
{
   
    [super viewDidLoad];
    self.keyValueStore = [NSUbiquitousKeyValueStore defaultStore];
}

然后分别实现两个按钮的点击事件:

- (IBAction)setValueButtonClickedHandler:(id)sender
{
   
    [self.keyValueStore setString:@"Hello iCloud" forKey:@"data"];
    [self.keyValueStore synchronize];
}

- (IBAction)getValueButtonClickedHandler:(id)sender
{
   
    NSString *string = [self.keyValueStore stringForKey:@"data"];
    NSLog(@"data = %@", string);
}

上面的代码用到了NSUbiquitousKeyValueStore的字符串存取方法,要注意的是当你设置了数据后一定要调用synchronize方法,否则这些设置操作是不会保存下来并且上传到iCloud上的。

该例子最好是能够准备两台设备(或模拟器)来进行测试,一台进行值设置,另外一台进行值的获取。

有时候,我们需要实时知道一些配置的变更,特别是在你有多台设备时(如同时拥有iPhone和iPad),想要在其中一台设备中变更某项信息,然后另外一台设备也能够感知并作出相应的调整。那么,这时候你需要监听NSUbiquitousKeyValueStoreDidChangeExternallyNotification通知,它能够告诉你的App所保存的key-value有变更。

我们将上面的例子进行改造,将设置字符串改为设置一个背景颜色值,并且设定它的key为bg,然后通过监听NSUbiquitousKeyValueStoreDidChangeExternallyNotification通知来改变VC的视图背景颜色。

首先,我们在viewDidLoad中进行监听通知:

- (void)viewDidLoad
{
   
    [super viewDidLoad];
    
    // 初始化keyValueStore
    self.keyValueStore = [NSUbiquitousKeyValueStore defaultStore];

    // 监听通知
    [[NSNotificationCenter defaultCenter] addObserverForName:NSUbiquitousKeyValueStoreDidChangeExternallyNotification object:self.keyValueStore queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
   
       
        if ([note.userInfo[NSUbiquitousKeyValueStoreChangedKeysKey] containsObject:@"bg"])
        {
   
            long long bgColorValue = [self.keyValueStore longLongForKey:@"bg"];
            UIColor *bgColor = [UIColor colorWithRed:(bgColorValue & 0xff) / 0xff
                                               green:(bgColorValue >> 8 & 0xff) / 0xff
                                                blue:(bgColorValue >> 16 & 0xff) / 0xff
                                               alpha:1];
            self.view.backgroundColor = bgColor;
        }
        
    }];
}

在上面代码中的通知处理,我们先通过NSUbiquitousKeyValueStoreChangedKeysKey来判断变更的key中是否包含bg这个key,如果存在则表示背景颜色有变更,再从keyValueStore中取出颜色值并转换成UIColor对象并设置成视图的背景颜色。

同时,两个按钮的点击事件处理如下:

- (IBAction)setValueButtonClickedHandler:(id)sender
{
   
    [self.keyValueStore setLongLong:0x00ff00 forKey:@"bg"];
    [self.keyValueStore synchronize];
}

- (IBAction)getValueButtonClickedHandler:(id)sender
{
   
    long long bgColorValue = [self.keyValueStore longLongForKey:@"bg"];
    UIColor *bgColor = [UIColor colorWithRed:(bgColorValue & 0xff) / 0xff
                                       green:(bgColorValue >> 8 & 0xff) / 0xff
                                        blue:(bgColorValue >> 16 & 0xff) / 0xff
                                       alpha:1];
    self.view.backgroundColor = bgColor;
}

通过上面的改动,在测试的过程中如果其中一台设备点击了set value按钮,则另外一台设备就会收到通知,并且变更视图的背景颜色。

文档数据同步

有时候会有这样的需求,如果开发的app是一款阅读类工具或者是一款壁纸工具,那么,我们会希望用户所下载的书籍或者壁纸会同步到不同的设备上来方便用户的操作,不需要再次去找到这本书或者这张图片进行重新下载。那么,iCloud提供了这样的服务,允许你把一份文档上传到iCloud中,然后其他设备再同步app上传的文档。

要想使用文档数据同步服务,就需要配合UIDocument来完成这项工作,具体的处理流程我先简单的描述一下,这样可以快速帮助到大家来理解机制的运作。

  1. UIDocument创建一个子类,该类型主要对app的中的文档进行管理。
  2. 重写UIDocumentcontentsForType:error:loadFromContents:ofType:error:方法,让文档根据app内部机制来实现保存和读取。
  3. 通过UIDocumentsaveToURL:forSaveOperation:completionHandler:将文档保存到iCloud容器中。
  4. 其他设备可以NSMetadataQuery来获取iCloud容器的文档列表,并更新到本地。

这里要注意一个问题,因为涉及到网络同步等相关的一些列操作,并不仅仅是当前应用进程在访问文件,系统的进程和其他应用进程也会对相关文件进行处理,所以不能通过NSFileManager直接对iCloud容器中的文件进行操作

同时也要弄清楚一个概念,其实UIDocument并不是为iCloud而设,它同样可以管理本地的文档。唯一区别是如果你的文档要放到iCloud,那么传给UIDocument的文档路径必须是以iCloud容器地址开始的路径,这样才能实现文档的同步

那么,下面来举例介绍如何进行文档数据的同步,假设开发的app是一款壁纸应用,在应用壁纸时会下载图片,然后讲它保存到iCloud中。另外的设备就可以自动地同步下载的图片并应用该壁纸。

首先把界面给搭建起来,如下图所示:

壁纸界面演示

界面是使用UICollectionView搭建的,代码在这里就不贴上来了,主要关注设置图片背景的处理过程。

首先,继承UIDocument类型创建其一个子类BackgroundImage,并为BackgroundImage声明一个传入UIImage对象的构造方法以及重写contentsForType:error:loadFromContents:ofType:error:两个方法代码如下:

@interface BackgroundImage : UIDocument

// 图片对象
@property (nonatomic, strong, readonly) UIImage *image;

// 构造方法
- (instancetype)initWithFileURL:(NSURL *)url image:(UIImage *)image;

@end

@implementation BackgroundImage

- (instancetype)initWithFileURL:(NSURL *)url image:(UIImage *)image
{
   
    if (self = [super initWithFileURL:url])
    {
   
        _image = image;
    }
    return self;
}

- (id)contentsForType:(NSString *)typeName error:(NSError * _Nullable __autoreleasing *)outError
{
   
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值