GarageStorage 0.2.3

GarageStorage 0.2.3

测试已测试
Lang语言 Obj-CObjective C
许可证 MIT
发布最后发布2016年7月

Sam Voigt 维护。



  • Sam Voigt

GarageStorage 被设计成完成两件事

  • 简化 Core Data 存储持久性
  • 消除 Core Data 数据模型版本并执行 xcdatamodel 迁移

它是以牺牲速度和健壮性为代价来做到这些的。在 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 和原语)、日期、键和值都是字符串或 NSNumbersGSMappableObjects 的字典以及任意类型的 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/拉取请求。祝您玩得愉快!