数据存储开发指南 · Unreal
数据存储是云服务提供的核心功能之一,可用于存放和查询应用数据。下面的代码展示了如何创建一个对象并将其存入云端:
// 构建对象
TSharedPtr<FLCObject> ToDo = MakeShared<FLCObject>("Todo");
// 为属性赋值
ToDo->Set("title", TEXT("工程师周会"));
ToDo->Set("content", TEXT("工程师周会"));
// 将对象保存到云端
ToDo->Save(FLeanCloudBoolResultDelegate::CreateLambda([=](bool bIsSuccess, const FLCError& Error) {
if (bIsSuccess) {
// 成功保存之后,执行其他逻辑
UE_LOG(LogTemp, Error, TEXT("%s"), *ToDo->GetObjectId());
} else {
// 异常处理
}
}));
我们为各个平台或者语言开发的 SDK 在底层都是通过 HTTPS 协议调用统一的 REST API,提供完整的接口对数据进行各类操作。
SDK 安装与初始化
对象
FLCObject
FLCObject
是云服务对复杂对象的封装,每个 FLCObject
包含若干与 JSON 格式兼容的属性值对(也称键值对,key-value pairs)。这个数据是无模式化的(schema free),意味着你不需要提前标注每个 FLCObject
上有哪些 key,你只需要随意设置键值对就可以,云端会保存它。
比如说,一个保存着单个 Todo 的 FLCObject
可能包含如下数据:
title: "给小林发邮件确认会议时间",
isComplete: false,
priority: 2,
tags: ["工作", "销售"]
数据类型
FLCObject
支持的数据类型包括 FString
、int
、Double
、Boolean
、Object
、Array
、Date
等等。你可以通过嵌套的方式在 Object
或 Array
里面存储更加结构化的数据。
FLCObject
还支持两种特殊的数据类型 Pointer
和 File
,可以分别用来存储指向其他 FLCObject
的指针以及二进制数据。
FLCObject
同时支持 GeoPoint
,可以用来存储地理位置信息。参见 GeoPoint。
以下是一些示例:
// 基本类型
FString String = TEXT("工程师周会");
int Interger = 10;
double Double = 20.0;
bool Boolean = true;
FDateTime Time = FDateTime::Now();
TArray<uint8> Data = {8, 16};
TLCMap Map;
Map.Add("Key", "Value");
TLCArray Array = {1, "HAHA", true};
TSharedPtr<FLCObject> Object = MakeShared<FLCObject>("Todo");
// 构建对象
TSharedPtr<FLCObject> TestObject = MakeShared<FLCObject>("TestObject");
TestObject->Set("testString", String);
TestObject->Set("testInt", Interger);
TestObject->Set("testDouble", Double);
TestObject->Set("testBoolean", Boolean);
TestObject->Set("testTime", Time);
TestObject->Set("testMap", Map);
TestObject->Set("testArray", Array);
TestObject->Set("testObject", Object);
TestObject->Save();
我们不推荐通过 NSData
在 FLCObject
里面存储图片、文档等大型二进制数据。每个 FLCObject
的大小不应超过 128 KB。如需存储大型文件,可创建 FLCFile
(暂不支持) 实例并将其关联到 FLCObject
的某个属性上。参见 文件。
注意:时间类型在云端将会以 UTC 时间格式存储,但是客户端在读取之后会转化成本地时间。
开发者中心 > 你的游戏 > 游戏服务 > 云服务 > 数据存储 > 结构化数据 中展示的日期数据也会依据操作系统的时区进行转换。一个例外是当你通过 REST API 获得数据时,这些数据将以 UTC 呈现。你可以手动对它们进行转换。
若想了解云服务是如何保护应用数据的,请阅读数据和安全。
构建对象
下面的代码构建 了一个 class 为 Todo
的 FLCObject
:
TSharedPtr<FLCObject> Object = MakeShared<FLCObject>("Todo");
在构建对象时,为了使云端知道对象属于哪个 class,需要将 class 的名字作为参数传入。你可以将云服务里面的 class 比作关系型数据库里面的表。一个 class 的名字必须以字母开头,且只能包含数字、字母和下划线。
保存对象
下面的代码将一个 class 为 Todo
的对象存入云端:
// 构建对象
TSharedPtr<FLCObject> ToDo = MakeShared<FLCObject>("Todo");
// 为属性赋值
ToDo->Set("title", TEXT("马拉松报名"));
ToDo->Set("priority", 2);
// 将对象保存到云端
ToDo->Save(FLeanCloudBoolResultDelegate::CreateLambda([=](bool bIsSuccess, const FLCError& Error) {
if (bIsSuccess) {
// 成功保存之后,执行其他逻辑
UE_LOG(LogTemp, Error, TEXT("%s"), *ToDo->GetObjectId());
} 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 | 该对象最后一次被修改的时间。 |
这些属性的值会在对象被存入云端时自动填入,代码中尚未保存的 FLCObject
不存在这些属性。
属性名(keys)只能包含字母、数字和下划 线。自定义属性不得以双下划线(__
)开头或与任何系统保留字段和内置属性(ACL
、className
、createdAt
、objectId
和 updatedAt
)重名,无论大小写。
属性值(values)可以是字符串、数字、布尔值、数组或字典(任何能以 JSON 编码的数据)。参见 数据类型。
我们推荐使用驼峰式命名法(CamelCase)为类和属性来取名。类,采用大驼峰法,如 CustomData
。属性,采用小驼峰法,如 imageUrl
。
获取对象
对于已经保存到云端的 FLCObject
,可以通过它的 objectId
将其取回:
FLCQuery Query = FLCQuery("Todo");
Query.Get("582570f38ac247004f39c24b", FLeanCloudQueryObjectDelegate::CreateLambda([](TSharedPtr<FLCObject> ObjectPtr, const FLCError& Error) {
if (ObjectPtr.IsValid()) {
FString Title = ObjectPtr->Get("title").AsString();
int Priority = ObjectPtr->Get("priority").AsInteger();
// 获取内置属性
FString ObjectID = ObjectPtr->GetObjectId();
FDateTime UpdateAt = ObjectPtr->GetUpdatedAt();
FDateTime CreatedAt = ObjectPtr->GetCreatedAt();
}
}));
如果你试图获取一个不存在的属性,SDK 不会报错,而是会返回默认值或者空。
同步对象
当云端数据发生更改时,你可以调用 FLCObject::Fetch
方法来刷新对象,使之与云端数据同步:
TSharedPtr<FLCObject> ToDo = MakeShared<FLCObject>("Todo", "5745557f71cfe40068c6abe0");
ToDo->Fetch(FLeanCloudBoolResultDelegate::CreateLambda([=](bool bIsSuccess, const FLCError& Error) {
if (bIsSuccess) {
// todo 已刷新
}
}));
刷新操作会强行使用云端的属性值覆盖本地的属性。因此如果本地有属性修改,FLCObject::Fetch
操作会丢弃这些修改。为避免这种情况,你可以在刷新时指定 需要刷新的属性,这样只有指定的属性会被刷新(包括内置属性 objectId
、createdAt
和 updatedAt
),其他属性不受影响。
TSharedPtr<FLCObject> ToDo = MakeShared<FLCObject>("Todo", "5745557f71cfe40068c6abe0");
ToDo->Fetch({"priority", "location"}, FLeanCloudBoolResultDelegate::CreateLambda([=](bool bIsSuccess, const FLCError& Error) {
if (bIsSuccess) {
// 只有 priority 和 location 会被获取和刷新
}
}));