添加参考字段
使用架构中的引用字段来表示模型对象之间的关系; 例如,表示分层数据或表示所有权。本章介绍如何添加对记录的引用,保存和获取带引用的记录,以及指定所有权以便自动删除相关记录。
关于在架构中建立模型关系
您可以使用引用字段类型来表示模型对象之间的一对一和一对多关系。在您的代码中,引用字段是一个CKReference
对象,它封装了目标记录的记录ID,并被添加到源记录中。要在架构中表示一对一关系,请将引用字段添加到源记录类型。
要表示模型对象之间的一对多关系,如果引用是从子记录到父记录(即向子记录添加引用字段),则效率更高。子记录是源,父记录是此架构中的目标。
例如,从Artist
到Artwork
存在一对多关系,反过来是从Artwork
到Artist
是一对一的关系。
要在架构中表示这些关系,将引用字段添加到名为artist
的相应Artwork
记录类型中。此参考字段将包含Artist
记录的记录ID 。
类似地,为了表示在对象模型中一个一对多关系从Artist
到Collection
,添加参考字段到Collection
记录。获取这些记录后,可以在模型对象之间创建适当的一对一和一对多关系。
创建参考字段
在开发期间,保存包含引用字段的记录以生成架构。通过向CKReference
源记录添加对象来表示架构中的一对一关系。
创建从一个记录到另一个记录的引用
创建或获取目标记录的记录ID。
CKRecordID *artistRecordID = [[CKRecordID alloc] initWithRecordName:@"Mei Chen"];
通过将目标的记录ID作为参数传递来创建引用对象。
CKReference *artistReference = [[CKReference alloc] initWithRecordID:artistRecordID action:CKReferenceActionNone];
将引用对象添加到源记录。
CKRecord *artworkRecord; … artworkRecord[@"artist"] = artistReference;
保存源记录以创建记录类型,如初始化容器中所述。如果要保存包含引用的多个记录,请在一次操作中保存所有记录,如“保存和获取多个记录的批处理操作”中所述。CloudKit将确保在源记录之前保存目标记录。
使用参考字段获取记录
不要在模型 - 视图 - 控制器设计模式中使用记录(CKRecord
对象)作为模型对象。而是从提取的记录创建单独的模型对象,尤其是当提取的记录包含引用时。您的应用程序负责解释记录之间的引用并在模型对象之间创建适当的关系。获取源记录时,不会自动获取目标记录。您的应用负责根据需要获取目标记录。根据引用所表现的关系类型,有不同的方法来获取目标和源记录。
如果可能,批量提取以解析模型对象之间的关系,如“保存和获取多个记录的批处理操作”所述。
解决一对一的关系
对于一对一关系,从源记录中获取引用字段并获取关联的目标记录。
获取一对一关系的目标
获取参考字段。
CKRecord *artworkRecord; … CKReference *referenceToArtist = artworkRecord[@"artist"];
从引用中获取目标记录ID。
CKRecordID *artistRecordID = artistReference.recordID;
获取目标记录。
[publicDatabase fetchRecordWithID:artistRecordID completionHandler:^(CKRecord *artistRecord, NSError *error) { if (error) { // Failed to fetch record } else { // Successfully fetched record } }];
将代码添加到
fetchRecordWithID:completionHandler:
完成处理程序参数。例如,添加代码以创建相应对象Artwork
和Artist
对象之间的一对一关系。
解决一对多关系
对于一对多关系,使用谓词一次获取父记录的所有子项。您可以获取将父项作为其目标记录的所有记录。
获取一对多关系的孩子
从
CKRecordID
先前获取的父记录ID()和父项的模型对象开始。例如,
Artist
从Artist
记录创建模型对象。__block Artist *artist = [[Artist alloc] initWithRecord:artistRecord];
使用,
__block
以便稍后可以在完成处理程序中访问父对象。创建谓词对象以获取子记录。
NSPredicate *predicate = [NSPredicate predicateWithFormat:@“artist = %@”, artistRecordID];
创建一个查询对象,指定要搜索的记录类型。
CKQuery *query = [[CKQuery alloc] initWithRecordType:@“Artwork” predicate:predicate];
在您的代码中,替换
@“Artwork”
为子记录类型的名称。执行提取。
CKDatabase *publicDatabase = [[CKContainer defaultContainer] publicCloudDatabase]; [publicDatabase performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) { if (error) { // Failed to fetch children of parent } else { // Create model objects for each child and set the one-to-many relationship from the parent to its children } }];
将代码添加到
else
创建模型对象之间的对应关系的语句中
用于保存和获取多个记录的批处理操作
将多个记录批量保存和提取放到单个操作中会更高效。如果记录类型包含引用字段,这一点尤为重要。您可以使用CKModifyRecordsOperation
对象在一个操作中保存新的源和目标记录。您可以创建对没有标识符的目标记录的引用。只要将源记录和目标记录一起保存,CloudKit就可以确保在相关CKRecord
对象的图形中,在源记录之前保存目标记录。您还可以使用CKFetchRecordsOperation
对象在一个操作中获取一组源记录的所有目标。
在单个操作中获取多个记录
添加要提取的记录的所有记录ID到一个数组中。
例如,要获取多个一对一关系,请将引用字段的所有目标记录ID添加到数组中。
通过将记录ID数组作为参数传递来创建获取记录操作对象。
CKFetchRecordsOperation *fetchRecordsOperation = [[CKFetchRecordsOperation alloc] initWithRecordIDs:fetchRecordIDs];
(可选)提供每个记录完成处理程序。
fetchRecordsOperation.perRecordCompletionBlock = ^(CKRecord *record, CKRecordID *recordID, NSError *error) { if (error) { // Retain the record IDs for failed fetches } else { // Create a model object and set any relationships to other models } };
如果要保存成功的单个记录中的数据,请提供每个记录完成处理程序。完成处理程序应为成功获取的记录创建模型对象,并且由于操作可能失败,因此应保留失败的获取的记录ID。
设置整个操作的完成处理程序。
fetchRecordsOperation.fetchRecordsCompletionBlock = ^(NSDictionary *recordsByRecordID, NSError *error) { if (error) { // Failed to fetch all or some of the records } else { // Update all associated views } };
如果在步骤3中将记录ID保存在每个记录完成处理程序中,则可以尝试再次获取失败的记录。
开始操作。
fetchRecordsOperation.database = [[CKContainer defaultContainer] publicCloudDatabase]; [fetchRecordsOperation start];
指定所有权以自动删除相关记录
您可以指定在删除目标记录时是否删除引用的源记录。例如,您可能希望在删除父级时删除一对多关系的子级。父记录拥有子记录。如果孩子拥有其他记录,他们也将被删除,导致一连串的删除。
您在创建引用对象时指定删除操作。要在删除目标时删除源记录,请将目标记录和CKReferenceActionDeleteSelf
操作参数作为initWithRecord:action:
方法传递。在“图库”示例中,指定删除艺术家时应删除属于艺术家的图稿。
CKReference *referenceToArtist = [[CKReference alloc] initWithRecord:artistRecord action:CKReferenceActionDeleteSelf];
artworkRecord[@"artist"] = referenceToArtist;
或者,检查CloudKit仪表板中的每条记录的DeleteSelf框。
当删除CKReferenceActionDeleteSelf
引用的第一个目标记录时,CloudKit会删除源记录。如果源记录具有多个CKReferenceActionDeleteSelf
引用,则即使存在某些其他目标记录,也可能将其删除,从而导致数据模型不一致。尝试设计您的架构,以便每个记录只有一个CKReferenceActionDeleteSelf
引用。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论