香港澳门葡京网址iOS学习笔记32-iCloud入门
一、iCloud云服务
iCloud是苹果提供的云端服务,用户可以以通讯录、备忘录、邮件、照片、音乐、视频等备份到讲话服务器并当挨家挨户苹果设备内一直开展共享而不管需关注数据并问题,甚至即便你的设备丢失后以同样贵新的装置上也可经Apple
ID登录同步。
苹果已经以云端存储功能开放给开发者,可以储存两看似数据:
key-value data
:
享受小量的非要配置数据到以的大都只实例,使用类于NSUserDefault
document
:
存储用户文档和运用数据到用户之iCloud账户
进行iCloud开发的准备干活:
- 当开发者中心上缔造AppleID,启用iCloud服务
- 转变对应之布置文件(
Provisioning Profile
),这里可以使用通配Bundle ID
- 如上2步凡对准真机的,调试模拟器可以忽略
- 开辟项目之
Capabilities
,找到iCloud服务并开启它 -
在iCloud服务的
Service
中勾选Key-value storae
和iCloud Documents
上述是利用模拟器的,使用真机的语句,下面2独红色感叹就会见熄灭
-
而的门类中即使见面多有一个
entitlements
文件 -
其中的情是自动生成的,就像这么的
- 任由真机还是模拟器,都亟需上手机的安中登陆iCloud账号
二、Key-Value的iCloud存储
使用和NSUserDefault
差不多,都是因键值对之样式储存。
动实例:
#import "iCloudKeysViewController.h"
@interface iCloudKeysViewController()
@property (strong, nonatomic) NSUbiquitousKeyValueStore *keyStore;
@property (strong, nonatomic) IBOutlet UILabel *textLabel;
@end
@implementation iCloudKeysViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.textLabel.text = @"Ready Go";
//获取iCloud配置首选项
self.keyStore = [NSUbiquitousKeyValueStore defaultStore];
//注册通知中心,当配置发生改变的时候,发生通知
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self
selector:@selector(ubiquitousKeyValueStoreDidChange:)
name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification
object:keyStore];
}
/* UI点击,点击改变按钮 */
- (IBAction)changeKey
{
[self.keyStore setString:@"Hello World" forKey:@"MyString"];
[self.keyStore synchronize];
NSLog(@"Save key");
}
/* 监听通知,当配置发生改变的时候会调用 */
- (void)ubiquitousKeyValueStoreDidChange:(NSNotification *)notification
{
NSLog(@"External Change detected");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Change detected"
message:@"Change detected"
delegate:nil
cancelButtonTitle:@"Ok"
otherButtonTitles:nil, nil];
[alert show];
//显示改变的信息
textLabel.text = [keyStore stringForKey:@"MyString"];
}
@end
三、Document的iCloud存储
核心类UIDocument
- 文档存储主要是应用
UIDocument
接近来好,这个类似提供了新建、修改、查询文档、打开文档、删除文档的效应。
UIDocument
针对文档的骤增、修改、删除、读取全部冲一个云端URL来好,对于开发者而言没有当地和云端的分,这样大大简化了支出进程。
云端URL的获得方式:
- 调用
NSFileManager
的对象方法
-(NSURL *)URLForUbiquityContainerIdentifier:(NSString *)identifier;
- 面用传递一个云端存储容器的绝无仅有标示,这个得错过自动生成的
entitlements
文件查看Ubiquity Container Identifiers
字段获得,如果污染nil
,代表第一单容器
增补知识 :
默认的首先只容器标识是
iCloud.$(CFBundleIdentifier)
,
其中$(CFBundleIdentifier)
代表Bundle ID
,那么根据使用之Bundle ID
就是可以查出自己的首先单容器的标识是iCloud.com.liuting.icloud.iCloudTest
UIDocument的目标方法:
/* 将指定URL的文档保存到iCloud(可以是新增或者覆盖,通过saveOperation参数设定)*/
- (void)saveToURL:(NSURL *)url
forSaveOperation:(UIDocumentSaveOperation)saveOperation
completionHandler:(void (^)(BOOL success))completionHandler;
/* 保存操作option */
typedef NS_ENUM(NSInteger, UIDocumentSaveOperation) {
UIDocumentSaveForCreating,/* 创建 */
UIDocumentSaveForOverwriting/* 覆盖写入 */
};
/* 打开文档,参数是打开文档成功回调 */
- (void)openWithCompletionHandler:(void (^)(BOOL success))completionHandler;
删去文档使用的凡NSFileManager的对象方法:
/* 删除指定URL下的文件 */
- (BOOL)removeItemAtURL:(NSURL *)URL
error:(NSError **)error;
注意事项:
UIDocument
于筹划之时节,没有供统一的积存方来囤积数据,需要我们去继承它们,重写2单对象方法好操作数据
/**
* 保存文档时调用
* @param typeName 文档文件类型
* @param outError 错误信息输出
* @return 文档数据
*/
-(id)contentsForType:(NSString *)typeName
error:(NSError **)outError;
/**
* 读取数据时调用
* @param contents 文档数据
* @param typeName 文档文件类型
* @param outError 错误信息输出
* @return 读取是否成功
*/
-(BOOL)loadFromContents:(id)contents
ofType:(NSString *)typeName
error:(NSError **)outError;
UIDocument
保存数据的原形:
拿A对承诺类型的数据转发为云端存储的NSData
或者NSFileWrapper
数据UIDocument
读取数据的本来面目:
用云端下载的NSData
或者NSFileWrapper
数量转发为A对承诺类型的数码
下是自家自从定义的Document类,继承给UIDocument:
LTDocument.h文件
#import <UIKit/UIKit.h>
@interface LTDocument : UIDocument
@property (strong, nonatomic) NSData *data;/*< 文档数据 */
@end
LTDocument.m文件
#import "LTDocument.h"
@implementation LTDocument
#pragma mark - 重写父类方法
/**
* 保存时调用
* @param typeName 文档文件类型后缀
* @param outError 错误信息输出
* @return 文档数据
*/
- (id)contentsForType:(NSString *)typeName
error:(NSError *__autoreleasing *)outError
{
if (!self.data) {
self.data = [NSData data];
}
return self.data;
}
/**
* 读取数据时调用
* @param contents 文档数据
* @param typeName 文档文件类型后缀
* @param outError 错误信息输出
* @return 读取是否成功
*/
- (BOOL)loadFromContents:(id)contents
ofType:(NSString *)typeName
error:(NSError *__autoreleasing *)outError
{
self.data = [contents copy];
return true;
}
@end
- 倘假定加载iCloud中的文档列表,就需要采取其他一个像样
NSMetadataQuery
- 普通考虑到网的由来并无会见一次性加载所有数据,而下
NSMetadataQuery
并指定searchScopes
为NSMetadataQueryUbiquitousDocumentScope
来界定查找iCloud文档数据。 - 使用
NSMetadataQuery
尚可通过谓词限定搜索关键字当消息,并当寻就后通过通告之款式通知客户端搜索的情。
下面是动示例:
1. 性质定义及宏定义:
#import "ViewController.h"
#import "LTDocument.h"
#define kContainerIdentifier @"iCloud.com.liuting.icloud.iCloudTest"
@interface ViewController () <UITableViewDataSource,UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UITextField *documentField;/*< 输入框 */
@property (weak, nonatomic) IBOutlet UILabel *documentShowLable;/*< 显示栏 */
@property (weak, nonatomic) IBOutlet UITableView *documentTableView;/* 文档列表 */
/* 文档文件信息,键为文件名,值为创建日期 */
@property (strong, nonatomic) NSMutableDictionary *files;
@property (strong, nonatomic) NSMetadataQuery *query;/*< 查询文档对象 */
@property (strong, nonatomic) LTDocument *document;/*< 当前选中文档 */
@end
2. 到手云端URL方法:
/**
* 取得云端存储文件的地址
* @param fileName 文件名,如果文件名为nil,则重新创建一个URL
* @return 文件地址
*/
- (NSURL *)getUbiquityFileURL:(NSString *)fileName{
//取得云端URL基地址(参数中传入nil则会默认获取第一个容器),需要一个容器标示
NSFileManager *manager = [NSFileManager defaultManager];
NSURL *url = [manager URLForUbiquityContainerIdentifier:kContainerIdentifier];
//取得Documents目录
url = [url URLByAppendingPathComponent:@"Documents"];
//取得最终地址
url = [url URLByAppendingPathComponent:fileName];
return url;
}
3. 询问文档列表方法
/* 从iCloud上加载所有文档信息 */
- (void)loadDocuments
{
if (!self.query) {
self.query = [[NSMetadataQuery alloc] init];
self.query.searchScopes = @[NSMetadataQueryUbiquitousDocumentsScope];
//注意查询状态是通过通知的形式告诉监听对象的
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self
selector:@selector(metadataQueryFinish:)
name:NSMetadataQueryDidFinishGatheringNotification
object:self.query];//数据获取完成通知
[center addObserver:self
selector:@selector(metadataQueryFinish:)
name:NSMetadataQueryDidUpdateNotification
object:self.query];//查询更新通知
}
//开始查询
[self.query startQuery];
}
/* 查询更新或者数据获取完成的通知调用 */
- (void)metadataQueryFinish:(NSNotification *)notification
{
NSLog(@"数据获取成功!");
NSArray *items = self.query.results;//查询结果集
self.files = [NSMutableDictionary dictionary];
//变量结果集,存储文件名称、创建日期
[items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSMetadataItem *item = obj;
//获取文件名
NSString *fileName = [item valueForAttribute:NSMetadataItemFSNameKey];
//获取文件创建日期
NSDate *date = [item valueForAttribute:NSMetadataItemFSContentChangeDateKey];
NSDateFormatter *dateformate = [[NSDateFormatter alloc]init];
dateformate.dateFormat = @"YY-MM-dd HH:mm";
NSString *dateString = [dateformate stringFromDate:date];
//保存文件名和文件创建日期
[self.files setObject:dateString forKey:fileName];
}];
//表格刷新
self.documentShowLable.text = @"";
[self.documentTableView reloadData];
}
4. UI点击波
#pragma mark - UI点击事件
/* 点击添加文档 */
- (IBAction)addDocument:(id)sender {
//提示信息
if (self.documentField.text.length <= 0) {
NSLog(@"请输入要创建的文档名");
self.documentField.placeholder = @"请输入要创建的文档名";
return;
}
//创建文档URL
NSString *text = self.documentField.text;
NSString *fileName = [NSString stringWithFormat:@"%@.txt",text];
NSURL *url = [self getUbiquityFileURL:fileName];
//创建云端文档对象
LTDocument *document = [[LTDocument alloc] initWithFileURL:url];
//设置文档内容
NSString *dataString = @"hallo World";
document.data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
//保存或创建文档,UIDocumentSaveForCreating是创建文档
[document saveToURL:url
forSaveOperation:UIDocumentSaveForCreating
completionHandler:^(BOOL success)
{
if (success) {
NSLog(@"创建文档成功.");
self.documentField.text = @"";
//从iCloud上加载所有文档信息
[self loadDocuments];
}else{
NSLog(@"创建文档失败.");
}
}];
}
/* 点击修改文档 */
- (IBAction)saveDocument:(UIButton *)sender {
if ([sender.titleLabel.text isEqualToString:@"修改文档"]) {
self.documentField.text = self.documentShowLable.text;
[sender setTitle:@"保存文档" forState:UIControlStateNormal];
} else if([sender.titleLabel.text isEqualToString:@"保存文档"]) {
[sender setTitle:@"修改文档" forState:UIControlStateNormal];
self.documentField.placeholder = @"请输入修改的文档内容";
//要保存的文档内容
NSString *dataText = self.documentField.text;
NSData *data = [dataText dataUsingEncoding:NSUTF8StringEncoding];
self.document.data = data;
//保存或创建文档,UIDocumentSaveForOverwriting是覆盖保存文档
[self.document saveToURL:self.document.fileURL
forSaveOperation:UIDocumentSaveForOverwriting
completionHandler:^(BOOL success)
{
NSLog(@"保存成功!");
self.documentShowLable.text = self.documentField.text;
self.documentField.text = @"";
}];
}
}
/* 点击删除文档 */
- (IBAction)removeDocument:(id)sender {
//提示信息
if (self.documentField.text.length <= 0) {
self.documentField.placeholder = @"请输入要删除的文档名";
return;
}
//判断要删除的文档是否存在
NSString *text = self.documentField.text;
NSString *fileName = [NSString stringWithFormat:@"%@.txt",text];
NSArray *fileNames = [self.files allKeys];
if (![fileNames containsObject:fileName]) {
NSLog(@"没有要删除的文档");
return;
}
//创建要删除的文档URL
NSURL *url = [self getUbiquityFileURL:fileName];
NSError *error = nil;
//删除文档文件
[[NSFileManager defaultManager] removeItemAtURL:url error:&error];
if (error) {
NSLog(@"删除文档过程中发生错误,错误信息:%@",error.localizedDescription);
return;
}
//从集合中删除
[self.files removeObjectForKey:fileName];
self.documentField.text = @"";
}
5. 视图控制器初始化和列表显示
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.documentTableView.delegate = self;
self.documentTableView.dataSource = self;
/* 从iCloud上加载所有文档信息 */
[self loadDocuments];
}
#pragma mark - UITableView数据源
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return self.files.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identtityKey = @"myTableViewCellIdentityKey1";
UITableViewCell *cell =
[self.documentTableView dequeueReusableCellWithIdentifier:identtityKey];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:identtityKey];
}
//显示文档名和文档创建日期
NSArray *fileNames = self.files.allKeys;
NSString *fileName = fileNames[indexPath.row];
cell.textLabel.text = fileName;
cell.detailTextLabel.text = [self.files valueForKey:fileName];
return cell;
}
#pragma mark - UITableView代理方法
/* 点击文档列表的其中一个文档调用 */
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.documentTableView cellForRowAtIndexPath:indexPath];
//获取文档URL
NSURL *url = [self getUbiquityFileURL:cell.textLabel.text];
//创建文档操作对象
LTDocument *document = [[LTDocument alloc] initWithFileURL:url];
self.document = document;
//打开文档并读取文档内容
[document openWithCompletionHandler:^(BOOL success) {
if(success){
NSLog(@"读取数据成功.");
NSString *dataText = [[NSString alloc] initWithData:document.data
encoding:NSUTF8StringEncoding];
self.documentShowLable.text = dataText;
}else{
NSLog(@"读取数据失败.");
}
}];
}
@end
点的代码Demo点这里:LearnDemo里面的iCloudDemo
这代码Demo只生Document的实例代码