GarageStorage 被设计成完成两件事
它是以牺牲速度和健壮性为代价来做到这些的。在 GarageStorage 中,只有一个类型的 Core Data 实体,并且所有的 NSObjects 都映射到这个对象上。NSObjects 之间的关系被保持,因此您确实获得了一些 Core Data 的图功能。此外,尽管它在生产应用中使用,但它的测试并不是非常彻底,并且对错误的输入不做太多的错误检查,所以请注意。
您的车库,或 GSGarage
,是一个中央管理器,它协调使用车库存储。它被称为车库,因为您几乎可以将任何东西停在那里,就像,你知道的,你的车库。车库处理备份 Core Data 栈以及数据的保存和检索。您将对象“停”在车库中,稍后“检索”它们。任何进入或离开车库的对象都必须订阅 GSMappableObject
协议。我们稍后再详细介绍这个。现在,重要的是要区分车库存储的运行方式和 Core Data 的运行方式:与 core data 本身存储对象不同,Garage Storage 在 Core Data 中存储对象的 JSON 表示。这有一些影响(下文解释),但最好的部分是无须迁移数据模型或任何其他东西,只需停放在您想要的位置!
首先,使用: [[GSGarage alloc] init]
创建一个车库。**警告:您应该只有一个车库实例。您的车库使用的 Managed Object Context 在您创建车库的线程上。强烈建议您在主线程上使用车库存储。您可以将其作为单例使用。或者不这样做。
@property (nonatomic, strong) GSGarage *garage;
self.garage = [GSGarage new];
您想停放在车库中的任何对象都必须遵守 <GSMappableObject>
。一个 <GSMappableObject>
必须实现方法 + (GSObjectMapping *)objectMapping
。
对象映射指定您要停放在对象上的属性。此外,它还可以指定一个属性,这是对象的唯一标识符。该属性必须是一个 NSString。例如,我可能有一个看起来像这样的个人对象:
@interface Person : NSObject <GSMappableObject>
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *SSN;
@end
您可以使用以下方法为类获取基础映射:[GSObjectMapping mappingForClass:[yourClass class]]
人的对象的映射可能看起来像
+ (GSObjectMapping *)objectMapping {
GSObjectMapping *mapping = [GSObjectMapping mappingForClass:[self class]];
[mapping addMappingsFromArray:@[@"name", @"ssn"]];
mapping.identifyingAttribute = @"ssn";
return mapping;
}
设置要映射的属性后,应设置标识属性,至少对于顶级对象(下面关于标识属性的说明)。在底层,您的对象被序列化为JSON,因此现在不要尝试存储任何复杂的属性。字符串、数字(包括 NSNumbers
和原语)、日期、键和值都是字符串或 NSNumbers
、GSMappableObjects
的字典以及任意类型的 GSMappableObjects
/此处列出的其他类型的数组都是可用的。
停放对象会将该对象的快照放入车库。如上所述,这与纯Core Data不同,在纯Core Data中,您的 NSManagedObject
的更改会直接反映在MOC中。使用GarageStorage,由于您正在停放快照,您将需要在任何时候将对象停放,才能使您对其所做的更改反映/持久化。可以多次停放相同的对象,这将更新该类和标识符的现有对象。要将 GSMappableObject
放置在车库中,请调用
[self.garage parkObjectInGarage:myPerson];
您还可以在车库中停放对象的数组(假设所有对象都是 GSMappableObjects
)
[self.garage parkObjectsInGarage:@[myBrother, mySister, myMom, myDad]];
要从一个车库中检索特定对象,您必须指定其类和标识符。
Person *myPerson = [self.garage retrieveObjectOfClass:[Person class] identifier:@"123-45-6789"];
您也可以检索给定类的所有对象
NSArray *allPeople = [self.garage retrieveAllObjectsOfClass:[Person class]];
要从车库中删除对象,您必须指定最初停放的可映射对象
[self.garage deleteObjectFromGarage:myPerson];
要删除类中的所有对象,使用
[self.garage deleteAllObjectsFromGarageOfClass:[Person class]];
您还可以从车库中删除所有对象
[self.garage deleteAllObjectsFromGarage];
如果您想跟踪对象的同步状态(例如,相对于一个web服务),可以实现 GSSyncableObject
协议,这需要您的对象具有同步状态属性
@property (nonatomic) GSSyncStatus syncStatus;
Garage Storage提供了以下同步状态选项
GSSyncStatusUndetermined,
GSSyncStatusNotSynced,
GSSyncStatusSyncing,
GSSyncStatusSynced
遵循 GSSyncableObject
的对象在放入车库时会自动设置它们的同步状态。但是,您也可以手动设置同步状态
- (BOOL)setSyncStatus:(GSSyncStatus)syncStatus forObject:(id<GSMappableObject>)object;
- (BOOL)setSyncStatus:(GSSyncStatus)syncStatus forObjects:(NSArray *)objects;
(如果对象中的一个或多个未在车库中找到,则这些函数将返回 NO
。)
您还可以确定车库中对象的同步状态
- (GSSyncStatus)syncStatusForObject:(id<GSMappableObject>)object;
最重要的是,您可以根据同步状态从车库检索对象
- (NSArray *)retrieveObjectsWithSyncStatus:(GSSyncStatus)syncStatus;
- (NSArray *)retrieveObjectsWithSyncStatus:(GSSyncStatus)syncStatus ofClass:(Class)cls;
停放、删除或修改对象的同步状态不会 themselves 将其更改持久化到磁盘。但是,在 GSGarage
中默认将 autosaveEnabled
设置为 YES
。这意味着任何修改车库的操作也会触发车库的保存。如果不想启用这种功能,请将 autosaveEnabled
设置为 NO
,然后显式调用 garage 保存
[self.garage saveGarage];
了解识别属性如何工作非常重要,这样您才能充分利用(读:考虑到)车库存储的特点。任何具有识别属性的物体都会在车库中作为独立的物体存储。如果您有许多相互引用的物体,这将非常棒,因为图形在其在车库中得到正确维护,因此对某个物体的更改将被指向它的其他物体“看到”。
或者,您不必在您的物体上设置识别属性。如果您在一个顶级物体上这样做(即直接在您上调用 parkObject
的物体),则该物体的映射的 JSON 表示形式将成为其标识符。如果您未对未命名的物体 A 进行命名,然后更改其一个属性,并再次将物体 A 停放,則現在車庫中將有 2 個 “複本” 的物体 A,因為其 JSON 映射,以及因此标识符,都已更改。如果物体 A 有标识符,則物体 A 會在第二次停放時被更新。对于顶级物体来说,有一个识别属性被认为是最佳实践。
然而,如果您的物体是顶级物体的属性,您可能希望它未经验证,尤其是如果它没有从逻辑上讲是其标识符的属性。一个未经验证的属性物体会以内联 JSON 的形式序列化,而不是像一个认证物体那样有一个单独的底层核心数据对象。这意味着您将无法直接通过类查询未经验证的子对象。
未经验证物体的主要优势有两个:首先,如果您没有自然的标识符,您不需要随机选择一个标识符。其次,在处理删除时存在底层差异。当您从车库中删除一个物体时,只会删除顶层 GSMappableObject
。如果它指向其他 GSMappableObjects
,则不会删除它们。车库存储不监视物体的保留计数,所以为了安全起见,只会移除指定的物体。然而,由于未经验证的物体是顶级对象的 JSON 的一部分,而它们并不是独立的底层对象,它们将被删除。sub 对象被认为是未经验证的,除非有充分的理由,这是最佳实践。
车库还可以做很多事情,包括使用您自己的 persistentStoreCoordinator
(这对于加密目的很有用),因此请查阅 GSGarage.h
以获取更多信息。始终欢迎 Feature/拉取请求。祝您玩得愉快!