数据存储开发指南 · Objective-C
数据存储是云服务提供的核心功能之一,可用于存放和查询应用数据。下面的代码展示了如何创建一个对象并将其存入云端:
// 构建对象
LCObject *todo = [LCObject objectWithClassName:@"Todo"];
// 为属性赋值
[todo setObject:@"工程师周会" forKey:@"title"];
[todo setObject:@"周二两点,全体成员" forKey:@"content"];
// 将对象保存到云端
[todo saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
// 成功保存之后,执行其他逻辑
NSLog(@"保存成功。objectId:%@", todo.objectId);
} else {
// 异常处理
}
}];
我们为各个平台或者语言开发的 SDK 在底层都是通过 HTTPS 协议调用统一的 REST API,提供完整的接口对数据进行各类操作。
SDK 安装与初始化
请阅读数据存储、即时通讯 Objective C SDK 配置指南。
对象
LCObject
LCObject
是云服务对复杂对象的封装,每个 LCObject
包含若干与 JSON 格式兼容的属性值对(也称键值对,key-value pairs)。这个数据是无模式化的(schema free),意味着你不需要提前标注每个 LCObject
上有哪些 key,你只需要随意设置键值对就可以,云端会保存它。
比如说,一个保存着单个 Todo 的 LCObject
可能包含如下数据:
title: "给小林发邮件确认会议时间",
isComplete: false,
priority: 2,
tags: ["工作", "销售"]
数据类型
LCObject
支持的数据类型包括 String
、Number
、Boolean
、Object
、Array
、Date
等等。你可以通过嵌套的方式在 Object
或 Array
里面存储更加结构化的数据。
LCObject
还支持两种特殊的数据类型 Pointer
和 File
,可以分别用来存储指向其他 LCObject
的指针以及二进制数据。
LCObject
同时支持 GeoPoint
,可以用来存储地理位置信息。参见 GeoPoint。
以下是一些示例:
// 基本类型
NSNumber *boolean = @(YES);
NSNumber *number = [NSNumber numberWithInt:2018];
NSString *string = [NSString stringWithFormat:@"%@ 流行音乐榜单", number];
NSDate *date = [NSDate date];
NSData *data = [@"Hello world!" dataUsingEncoding:NSUTF8StringEncoding];
NSArray *array = [NSArray arrayWithObjects: string, number, nil];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys: number, @"number", string, @"string", nil];
// 构建对象
LCObject *testObject = [LCObject objectWithClassName:@"TestObject"];
[testObject setObject:boolean forKey:@"testBoolean"];
[testObject setObject:number forKey:@"testInteger"];
[testObject setObject:string forKey:@"testString"];
[testObject setObject:date forKey:@"testDate"];
[testObject setObject:data forKey:@"testData"];
[testObject setObject:array forKey:@"testArray"];
[testObject setObject:dictionary forKey:@"testDictionary"];
[testObject saveInBackground];
我们不推荐通过 NSData
在 LCObject
里面存储图片、文档等大型二进制数据。每个 LCObject
的大小不应超过 128 KB。如需存储大型文件,可创建 LCFile
实例并将其关联到 LCObject
的某个属性上。参见 文件。
注意:时间类型在云端将会以 UTC 时间格式存储,但是客户端在读取之后会转化成本地时间。
云服务控制台 > 数据存储 > 结构化数据 中展示的日期数据也会依据操作系统的时区进行转换。一个例外是当你通过 REST API 获得数据时,这些数据将以 UTC 呈现。你可以手动对它们进行转换。
若想了解云服务是如何保护应用数据的,请阅读数据和安全。
构建对象
下面的代码构建了一个 class 为 Todo
的 LCObject
:
LCObject *todo = [LCObject objectWithClassName:@"Todo"];
// 等同于
LCObject *todo = [[LCObject alloc] initWithClassName:@"Todo"];
在构建对象时,为了使云端知道对象属于哪个 class,需要将 class 的名字作为参数传入。你可以将云服务里面的 class 比作关系型数据库里面的表。一个 class 的名字必须以字母开头,且只能包含数字、字母和下划线。
保存对象
下面的代码将一个 class 为 Todo
的对象存入云端:
// 构建对象
LCObject *todo = [LCObject objectWithClassName:@"Todo"];
// 为属性赋值
[todo setObject:@"马拉松报名" forKey:@"title"];
[todo setObject:@2 forKey:@"priority"];
// 将对象保存到云端
[todo saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
// 成功保存之后,执行其他逻辑
NSLog(@"保存成功。objectId:%@", todo.objectId);
} else {
// 异常处理
}
}];
为了确认对象已经保存成功,我们可以到 云服务控制台 > 数据存储 > 结构化数据 > Todo
里面看一下,应该会有一行新的数据产生。点一下这个数据的 objectId
,应该能看到类似这样的内容:
{
"title": "马拉松报名",
"priority": 2,
"ACL": {
"*": {
"read": true,
"write": true
}
},
"objectId": "582570f38ac247004f39c24b",
"createdAt": "2017-11-11T07:19:15.549Z",
"updatedAt": "2017-11-11T07:19:15.549Z"
}
注意,无需在 云服务控制台 > 数据存储 > 结构化数据 里面创建新的 Todo
class 即可运行前面的代码。如果 class 不存在,它将自动创建。
以下是一些对象的内置属性,会在对象保存时自动创建,无需手动指定:
内置属性 | 类型 | 描述 |
---|---|---|
objectId | NSString | 该对象唯一的 ID 标识。 |
ACL | LCACL | 该对象的权限控制,实际上是一个 JSON 对象,控制台做了展现优化。 |
createdAt | NSDate | 该对象被创建的时间。 |
updatedAt | NSDate | 该对象最后一次被修改的时间。 |
这些属性的值会在对象被存入云端时自动填入,代码中尚未保存的 LCObject
不存在这些属性。
属性名(keys)只能包含字母、数字和下划线。自定义属性不得以双下划线(__
)开头或与任何系统保留字段和内置属性(ACL
、className
、createdAt
、objectId
和 updatedAt
)重名,无论大小写。
属性值(values)可以是字符串、数字、布尔值、数组或字典(任何能以 JSON 编码的数据)。参见 数据类型。
我们推荐使用驼峰式命名法(CamelCase)为类和属性来取名。类,采用大驼峰法,如 CustomData
。属性,采用小驼峰法,如 imageUrl
。
获取对象
对于已经保存到云端的 LCObject
,可以通过它的 objectId
将其取回:
LCQuery *query = [LCQuery queryWithClassName:@"Todo"];
[query getObjectInBackgroundWithId:@"582570f38ac247004f39c24b" block:^(LCObject *todo, NSError *error) {
// todo 就是 objectId 为 582570f38ac247004f39c24b 的 Todo 实例
NSString *title = todo[@"title"];
int priority = [[todo objectForKey:@"priority"] intValue];
// 获取内置属性
NSString *objectId = todo.objectId;
NSDate *updatedAt = todo.updatedAt;
NSDate *createdAt = todo.createdAt;
}];
对象拿到之后,可以通过 get
方法来获取各个属性的值。注意 objectId
、updatedAt
和 createdAt
这三个内置属性不能通过 get
获取或通过 set
修改,只能由云端自动进行填充。尚未保存的 LCObject
不存在这些属性。
如果你试图获取一个不存在的属性,SDK 不会报错,而是会返回 nil