HRCoder 1.3.3

HRCoder 1.3.3

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

Nick Lockwood 维护。



HRCoder 1.3.3

  • 作者:
  • Nick Lockwood

目的

HRCoder 是 NSKeyedArchiver 和 NSKeyedUnarchiver 类的替代品。虽然 NSKeyedArchiver 按标准 Plist 格式写入数据,但 Plist 的结构使得阅读变得困难,几乎无法手动生成。

HR 代表 Human Readable(可读性)。HRCoder 用比 NSKeyedArchiver 简单的格式保存文件;标准对象(如字符串、字典、数组、数字、布尔值和二进制数据)都使用标准的 Plist 原语进行保存和加载,其他任何类型的对象都保存为一个简单的字典,并添加一个 $class 键来表示对象类型。

这使得手动生成与 HRCoder 兼容的 Plist 文件变得简单,然后可以使用标准的 NSCoding 协议进行加载。您还可以安全地读取和手动编辑由 HRCoder 类保存的文件,而不用担心文件损坏。

HRCoding 使用的简单字典/数组格式也可以轻松存储为 JSON,从而为序列化提供了更多选项(NSKeyedArchiver 与 Plists 相关联,不能轻易用于保存为 JSON,除非作为中间步骤创建 Plist)。

HRCoder 设计与 AutoCoding 库(https://github.com/nicklockwood/AutoCoding)一起工作,该库可以自动为您的类写入 initWithCoder:encodeWithCoder: 方法。查看 AutoTodoList 示例以了解其工作原理。

HRCoder 还旨在与 BaseModel 库(https://github.com/nicklockwood/BaseModel)紧密协作,该库可以以最小的工作量为基础构建一个强大的模型层次结构。查看 BaseModel 仓库中包含的 HRTodoList 示例,了解这些库如何协同工作。

支持的操作系统 & SDK 版本

  • 支持构建目标 - iOS 8.0 / Mac OS 10.9(Xcode 6.0,Apple LLVM 编译器 6.0)
  • 最早支持的部署目标 - iOS 5.0 / Mac OS 10.7
  • 最早兼容的部署目标 - iOS 4.0 / Mac OS 10.6

注意:'支持' 意味着该库已为此版本进行测试。'兼容' 意味着该库应该在该 OS 版本上运行(即它不依赖于任何不可用的 SDK 特性),但不再测试兼容性,可能需要调整或错误修复才能正确运行。

ARC 兼容性

截至版本 1.3,HRCoder 需要 ARC。如果您希望在非 ARC 项目中使用 HRCoder,只需将 -fobjc-arc 编译器标志添加到 HRCoder.m 类文件中。为此,请转到目标设置中的编译阶段标签,打开编译源代码组,在列表中双击 HRCoder.m 并在弹出窗口中输入 -fobjc-arc。

如果您想将整个项目转换为ARC,请注释掉HRCoder.m中的#error行,然后在Xcode中选择Edit > Refactor > Convert to Objective-C ARC...工具,并确保您希望使用ARC的所有文件都勾选(包括HRCoder.m)。

线程安全

从多个线程并发访问单个HRCoder实例是不安全的,但使用HRCoder类的方法进行编码和解码对象是完全线程安全的。

安装

要使用HRCoder,只需将HRCoder.h和.m文件拖动到您的项目中。

HRCoder属性

@property (nonatomic, assign) HRCoderFormat outputFormat;

此属性可用于设置序列化HRCoded对象的输出格式。可能的值有HRCoderFormatXMLHRCoderFormatJSONHRCoderFormatBinary。默认值是HRCoderFormatXML,它会产生一个XML Plist。

HRCoder方法

HRCoder实现了以下方法,这些方法与NSKeyedArchiver和NSKeyedUnarchiver类的那些方法相匹配。

+ (id)unarchiveObjectWithPlistOrJSON:(id)plistOrJSON;

从编码的Plist或JSON对象构造一个对象树,并返回它。plistOrJSON参数可以是Plist或JSON格式本机支持的任何对象。这通常是一个容器对象,如NSDictionary或NSArray。如果提供了其他类型的对象,则将返回未修改的对象。

请注意,此对象实际上不一定是加载自Plist或JSON文件,您可以按编程方式创建这样一个对象。

+ (id)unarchiveObjectWithData:(NSData *)data;

从NSData对象加载序列化的plist,并通过在文件中的根对象上调用unarchiveObjectWithPlist:来返回一个未归档的对象树。支持文本、JSON、XML或二进制格式化的数据。使用可变容器解序列化数据以确保归档数组和字典的可变性。如果您更喜欢不可变对象,则可以直接使用NSPropertyListSerializationNSJSONSerialization类加载对象。

+ (id)unarchiveObjectWithFile:(NSString *)path;

加载Plist格式的数据文件,并通过在文件中调用unarchiveObjectWithData:来返回一个未归档的对象树。

+ (id)archivedPlistWithRootObject:(id)object;

将传入的对象编码为与Plist兼容的层次结构,并返回它。结果对象通常将是NSDictionary、NSArray、NSString、NSData、NSDate或NSNumber之一。然后将此对象安全地传递给NSPropertyListSerialisation进行转换为原始数据或保存到文件。

+ (id)archivedJSONWithRootObject:(id)object;

将传入的对象编码为与JSON兼容的层次结构,并返回它。结果对象通常是NSDictionary、NSArray、NSString、NSNumber或NSNull之一。然后将此对象安全地传递给NSPropertyListSerialisation进行转换为原始数据或保存到文件。

+ (NSData *)archivedDataWithRootObject:(id)rootObject;

通过调用archivedPlistWithRootObject:将传入的对象编码,然后使用XML属性列表格式将其序列化为数据。

+ (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path;

通过调用archivedDataWithRootObject:将传入的对象编码,然后将它保存到指定的文件路径。文件以原子方式保存以防止数据损坏。

- (id)initForReadingWithData:(NSData *)data;

此方法用于从可以传递给类的initWithCoder:方法的编码NSData对象创建一个HRCoder实例。它主要为了与具有相同方法的NSKeyedUnarchiver类兼容。数据必须包含一个plist编码的NSDictionary对象。不支持此方法中其他根对象类型(您可以使用unarchiveObjectWithData:方法加载包含其他根对象类型的数据)。

- (id)initForWritingWithMutableData:(NSMutableData *)data;

此方法用于创建一个用于写入数据对象的 HTCoder 对象。创建 HRCoder 实例后,可以将它传递给对象的 encodeWithCoder: 方法以对其进行编码。编写完对象后,调用 finishEncoding 将序列化的 plist 数据写入 NSMutableData 对象。

- (void)finishDecoding;

使用 initForReadingWithData: 方法打开的数据完成解码。

- (void)finishEncoding;

使用 initForWritingWithMutableData: 方法打开文件后,这将关闭文件并将序列化后的数据写入最初指定的 NSMutableData 对象。

Plist 结构

任何普通的 Plist 都可以使用 HECoder 加载,其行为与使用 NSPropertyListSerialization 加载相同。要向 Plist 中添加自定义类,定义对象时将其视为字典,但添加一个额外的 $class 键,指定对象的类名。例如,此代码会生成一个普通的 NSDictionary

<dict>
    <key>coming</key>
    <string>Hello</string>
    <key>going</key>
    <string>Goodbye</string>
</dict>

但是这将加载一个 Greetings 类型的对象(假设这个类存在于你的项目中)。

<dict>
    <key>$class</key>
    <string>Greetings</string>
    <key>coming</key>
    <string>Hello</string>
    <key>going</key>
    <string>Goodbye</string>
</dict>

NSCoding 的另一个特性是普通 Plist 不支持的循环引用。HRCoding 使用别名机制支持这

<dict>
    <key>$alias</key>
    <string>path.to.the.object</string>
</dict>

别名值是原始对象在层次结构中的键路径。为了了解它是如何工作的,这里有一个简单的例子

<dict>
    <key>object1</key>
    <string>Hello World</string>
    <key>object2</key>
    <dict>
        <key>$alias</key>
        <string>object1</string>
    </dict>
</dict>

一旦加载,object1 和 object2 属性都将指向同一个 "Hello World" 字符实例(不仅是相同的价值,而且是相同的实际对象)。这也适用于数组 - 只需要使用数组索引作为别名键

<array>
    <string>Hello World</string>
    <dict>
        <key>$alias</key>
        <string>0</string>
    </dict>
</array>

别名中允许使用前向引用(即对层次结构中稍后声明的对象进行别名化),然而应尽可能避免这样做,因为它涉及到在反序列化对象树时插入 HRCoderAliasPlaceholder 对象,然后在稍后替换这些对象,这会带来轻微的性能损失。

注意,如果你使用别名,你应该小心不要在 initWithCoder: 方法中对反序列化对象调用方法,因为它们可能在加载完成之前不是预期的类型。

发布说明

版本 1.3.2

  • 修复了在 JSON 文件中编码二进制数据时的崩溃问题(影响了可变字符串)
  • 修复了 Xcode 6 中的一些附加警告

版本 1.3.1

  • 修复了编码条件对象中的错误
  • HRCoder 现在可以使用基于 64 的编码将 NSData 对象编码为 JSON

版本 1.3

  • outputFormat 枚举现在是 HRCoderFormat 类型,包含 JSON 作为选项
  • 使用 JSON 输出格式时,NSData 和 NSDate 对象现在以与 JSON 兼容的格式编码
  • HRCoder 现在可以加载以 JSON 格式编码的数据
  • 现在符合 -Weverything 警告级别
  • 在 ARC中使用时性能改进
  • HRCoder 现在需要 ARC

版本 1.2.3

  • 修复了重写 isEqual 的对象被错误别名的错误
  • NSNumber、NSDate 和短 NSString 类型的对象将不再被别名为
  • 现在符合 -Wall 和 -Wextra 警告级别

版本 1.2.2

  • 修复了解码时可能会跳过对象的错误,这取决于 plist 中项目的顺序
  • 添加了 CocoaPods podspec

版本 1.2.1

  • 修复了嵌套 NSDictionaries 无法正确解码的错误

版本 1.2

  • 添加了initForReadingWithData:initForWritingWithMutableData:方法,这些方法提高了与NSKeyedArchiver/Unarchiver类接口的兼容性。
  • 添加了输出格式(outputFormat)属性,用于设置保存时的Plist格式

版本 1.1.3

  • 修复了由于过度释放解码对象导致的分析器警告

版本 1.1.2

  • 修复了在尝试归档nil对象属性时崩溃的问题

版本 1.1.1

  • HRCoder现在在对象解归档后调用awakeAfterUsingCoder:方法。
  • HRCoder现在在归档对象之前调用对象的classForCoderreplacementObjectForCoder:方法。

版本 1.1

  • 添加了unarchiveObjectWithData:archivedDataWithRootObject:方法
  • HRCoder现在默认以XML格式保存,而不是二进制格式
  • 现在支持Mac OS 10.6上的32位CPU

版本 1.0

  • 初始发布