AutoCoding 2.2.3

AutoCoding 2.2.3

测试已测试
Lang语言 Obj-CObjective C
许可 zlib
发布最新发布2017年10月

Nick Lockwood 维护。



  • 作者:
  • Nick Lockwood

目的

AutoCoding 是 NSObject 类别,为任何对象提供 NSCoding 的自动支持。这意味着您不必亲自实现 initWithCoder:encodeWithCoder: 方法,您的应用程序中的所有模型类都可以在不需编写任何额外代码的情况下保存或从文件中加载。

当然,没有任何自动的系统能够读取您的想法,因此 AutoCoding 对您如何设计类有一定的限制;例如,您应该避免使用通过 NSValue 已经符合 NSCoding 的结构体。

使用 AutoCoding 绝对不是一刀切的决策。您可以在您项目的任何类上实现自己的 NSCoding 或 NSCopying 方法,并简单地覆盖自动生成的方法。

支持的操作系统和 SDK 版本

  • 支持的构建目标 - iOS 9.3 / Mac OS 10.11 (Xcode 7.3, Apple LLVM 编译器 7.1)
  • 最早支持的部署目标 - iOS 7.0 / Mac OS 10.10
  • 最早兼容的部署目标 - iOS 4.3 / Mac OS 10.6

注意:"支持" 意味着该库已经与该版本进行了测试。"兼容" 意味着该库应该可以在该操作系统版本上运行(即它不依赖于不可用的 SDK 功能),但不再进行兼容性测试,可能需要调整或修复错误才能正确运行。

ARC 兼容性

AutoCoding 兼容 ARC 和非 ARC 编译目标。

线程安全性

AutoCoding 完全线程安全。

安装

要在您的项目中使用 AutoCoding 类别,只需将 AutoCoding.h 和 .m 文件拖动到您的项目中即可。

安全

从2.0版本开始,AutoCoding自动支持NSSecureCoding协议,默认情况下,对所有对象调用+supportsSecureCoding方法都返回YES。除此之外,假设你没有重写+supportsSecureCoding以返回NO,当尝试解码一个类型与被分配属性不匹配的类时,AutoCoding将自动抛出异常。这使得恶意方难以构造一个NSCoded文件,当你的应用加载此文件时,不会执行你不希望执行的代码。

NSCopying

从2.1版本开始,NSCopying不再自动实现,因为它与Core Data NSManagedObjects存在一些兼容性问题。如果你想实现复制,可以通过以下方式轻松实现:遍历可编码属性的键,并逐个将这些属性复制到新对象实例中。

- (id)copyWithZone:(id)zone
{
    id copy = [[[self class] alloc] init];
    for (NSString *key in self.codableProperties)
    {
        [copy setValue:[self valueForKey:key] forKey:key];
    }
    return copy;
}

为了正确支持NSCopying,你还应该重写任何你要用于复制的对象的-hash-isEqual:方法,以确保复制对象具有相同的哈希值,并且与原始对象相等。

提示

  1. 要排除你的对象中某些属性被编码,可以采取以下任何一种方式

    • 只使用一个ivar,不要声明匹配的@property。
    • 将ivars的名称更改为不符合KVC规范(例如,不与属性相同,或者属性名称带有下划线前缀)。你可以使用@synthesize方法做到这一点,例如:@synthesize foo = unencodableFoo;
    • 重写+codableProperties方法
  2. 如果你想在对属性进行加载之前或之后进行类初始化,重写(setWithCoder:)方法,并在应用你自己的逻辑之前或之后调用超实现,如下所示

    - (void)setWithCoder:(NSCoder *)coder
    {
        //pre-initialisation
        [super setWithCoder:coder];
        //post-initialisation
    }
    

    请注意,与先前版本不同,在使用initWithCoder:时,不调用init方法。

  3. 如果对象通过NSCoding加载后,你要执行某些清理、后处理或替换不同的对象,你可以使用NSObject类引用中定义的awakeAfterUsingCoder:方法。

  4. 通过重写setWithCoder:和/or encodeWithCoder:方法,可以添加额外的编码/解码逻辑。只要调用[super ...]实现,自动编码仍然会起作用。

  5. 如果你想在给定的属性类型中替换不同的类 - 例如,如果你更改了类名,但希望保留使用旧类名保存的文件兼容性,可以通过使用[NSKeyedUnArchiver setClass:forClassName:]方法为给定的名称替换不同的类。

  6. 如果你有不支持NSCoding的类型(例如,一个结构体)的属性,并且你想通过应用转换函数自己进行编码,通过更改ivar名称将属性标记为不可编码,并重写setWithCoder:和encodeWithCoder:方法(记得在调用超实现那些方法的同时自动加载和保存对象的其它属性)。如下所示:

    @synthesize uncodableProperty = noencode_uncodableProperty; //non-KVC-compliant name
    
    - (void)setWithCoder:(NSCoder *)coder
    {
        [super setWithCoder:coder];
        self.uncodableProperty = DECODE_VALUE([coder decodeObjectForKey:@"uncodableProperty"]);
    }
    
    - (void)encodeWithCoder:(NSCoder *)coder
    {
        [super encodeWithCoder:coder];
        [coder encodeObject:ENCODE_VALUE(self.newProperty) forKey:@"uncodableProperty"];
    }
    
  7. 如果你更改了属性的名称,但想检查旧的键名称的存在性以进行向后兼容性,重写setWithCoder:方法并添加检查旧属性,如下所示:

    - (void)setWithCoder:(NSCoder *)coder
    {
        [super setWithCoder:coder];
        self.newProperty = [coder objectForKey:@"oldProperty"] ?: self.newProperty;
    }
    
  8. 如果你更改了属性的名称,但想使用旧的键名称进行加载和保存以进行向后兼容性,给新属性一个不符合KVC规范的ivar名称,并重写setWithCoder:/encodeWithCoder:方法以使用旧名称保存和加载属性(记得调用那些方法的超实现以自动加载和保存对象的其它属性)。如下所示:

    @synthesize newProperty = noencode_newProperty; //non-KVC-compliant name
    
    - (void)setWithCoder:(NSCoder *)coder
    {
        [super setWithCoder:coder];
        self.newProperty = [coder objectForKey:@"oldProperty"];
    }
    
    - (void)encodeWithCoder:(NSCoder *)coder
    {
        [super encodeWithCoder:coder];
        [coder encodeObject:self.newProperty forKey:@"oldProperty"];
    }
    

发布说明

版本 2.2.2

  • 修复了最新 Xcode 上的警告
  • 添加了可空性和轻量级泛型
  • 将方法和属性文档移入头文件中

版本 2.2.1

  • 添加缺失的导入,Xcode 6.x 需要

版本 2.2

  • 现在支持 @dynamic 属性,允许与 NSManagedObject 一起使用 AutoCoding
  • 添加了对其他整数类型的支持
  • 修复了单元测试

版本 2.1

  • 移除了自动 NSCopying 实现(详细信息请参阅 README)
  • +codableProperties 方法将不再包括不符合 KVC 的 ivar 的属性,即使它们是读写属性。这使得标记读写属性为不可编码变得更加容易,无需重写方法
  • +uncodableProperties 方法现已弃用
  • dictionaryRepresentation 方法将不再包含 nil 值的 NSNull 条目(这些值将简单地从结果中省略)
  • 现在符合 -Weverything 警告级别

版本 2.0.3

  • 现在符合 -Wextra 警告级别

版本 2.0.2

  • 修复了长期以来未编码的属性 / keys 会被忽略的读取属性问题。

版本 2.0.1

  • 修复了 AutoCoding 的 NSCopying 实现将不支持具有 copy 语义的属性,因为它缺少 copyWithZone: 实现的 bug
  • 现在返回 YES 以支持 respondsToSelector:@selector(copyWithZone:).

版本 2.0

  • AutoCoding 现在自动实现 NSSecureCoding 协议
  • AutoCoding 现在自动检测属性类型,如果编解码的类与其期望的类型不匹配,则默认抛出异常
  • AutoCoding 2.0 与先前的版本数据兼容,但在升级时可能需要代码更改。

版本 1.3.1

  • 修复了与 CoreData 的问题,AutoCoding 的 copyWithZone: 实现与 NSManagedObject 冲突
  • 由于自动 NSCopying 实现的变化,调用 [super copyWithZone:] 将不再正常工作。如果需要这样做,请重写 copy 方法并调用 [super copy] 代替
  • 添加 Podspec 文件

版本 1.3

  • AutoCoding 不再尝试编码虚拟属性。只有 ivar 支持的属性将被编码
  • 添加 dictionaryRepresentation 方法以快速访问类的所有属性
  • codableKeys 和 uncodableKeys 方法现在是类方法,这使得它们更容易在工厂方法中使用
  • 类级别的 codable/uncodableKeys 方法现在只返回调用其所在的类上的属性,而不是所有超类
  • 不再需要调用 [super codableKeys] 或 [super uncodableKeys] 并合并数组,当在子类上重写 codableKeys 或 uncodableKeys 类方法时(不建议重写 codableKeys 实例方法)

版本 1.2.1

  • writeToFile:atomically: 方法现在返回 BOOL 以指示成功
  • 更改了分类文件名

版本 1.2

  • 只要只读属性有一个符合 KVC 的 ivar(即名称与属性匹配或带有 _ 前缀的属性),就可以复制和编码
  • initWithCoder: 不再调用 [self init],符合 Apple 文档
  • codableKeys 方法现在使用缓存以提高性能
  • 公开了之前私有的由 BaseModel 库使用的 setWithCoder: 方法

版本 1.1.2

  • 将构造函数切换为新类型安全的 instancetype 而不是 id,这使得在加载的实例上使用点语法属性访问器变得更简单。

版本 1.1.1

  • 只读属性现在不包括在 codableKeys 中
  • 添加了单元测试

版本 1.1

  • 添加了自动 NSCopying 实现
  • writeToFile现在遵循useAuxiliaryFile参数

版本1.0

  • 初始发布