EPISODE · Mar 13, 2016 · 7 MIN
399. nshipster-NSCoding : NSKeyedArchiver
from iOSDevLog · host iOSDevLog
http://nshipster.cn/nscoding/ NSCoding / NSKeyedArchiver Mattt Thompson撰写、 Yu Jin翻译、 发布于2013年5月13日 在构建应用程序时,一个重要的架构决策问题是在每次启动之间如何持久化数据。问题是如何精准的重现最后一次关闭应用前的状态;如何描述对象图以使下次完美地重新构建。 在 iOS 和 OS X 上, 苹果提供了两种选择 :Core Data 或 NSKeyedArchiver / NSKeyedUnarchiver (用来将遵循 的类序列化) 或者更确切地说:有三种选择,如果你算上NSURLCache的话. 在client-server应用场景下,在每次启动时加载必要的数据是一种可行的设计,尤其是结合磁盘缓存,存储服务器的响应,这样当发送对应请求的时候可以立即返回。在实践中,网络层和对象层上的缓存结合是可取的。 当涉及到建模,查询,遍历,持久化复杂的对象图,那Core Data是无可代替的。Core Data 是把大锤子,但不是所有的问题都是足够大的钉子。 Core Data 和 NSKeyedArchiver客观和常见的比较可能是这样的: Core Data NSKeyedArchiver Entity Modeling Yes No Querying Yes No Speed Fast Slow Serialization Format SQLite, XML, or NSData NSData Migrations Automatic Manual Undo Manager Automatic Manual 等等。在这场对决中,没有什么可比性,它看起来是一边倒的局势。 ...也就是说,直到你从一个稍微不同的角度看它: Core Data NSKeyedArchiver Persists State Yes Yes Pain in the Ass Yes No 通过这些对比,在某些情况下NSKeyedArchiver是一个完全合理的选择。并非所有的应用程序需要查询的数据。并非所有的应用程序需要自动迁移。并非所有的应用程序处理大型或复杂的对象图。而且应用中确实是有一些模块更好地被一个简单的方案解决。 这篇文章将关注如何,何时,为什么选择NSKeyedArchiver 和 NSCoding。希望能提供给亲爱的读者们以启发选择最合适的工具。 NSCoding 是一个简单的协议,有两个方法: -initWithCoder: 和 encodeWithCoder:。遵循NSCoding协议的类可以被序列化和反序列化,这样可以归档到磁盘上或分发到网络上。 举个例子: Objective-C @interface Book : NSObject @property NSString *title; @property NSString *author; @property NSUInteger pageCount; @property NSSet *categories; @property (getter = isAvailable) BOOL available; @end @implementation Book #pragma mark - NSCoding - (id)initWithCoder:(NSCoder *)decoder { self = [super init]; if (!self) { return nil; } self.title = [decoder decodeObjectForKey:@"title"]; self.author = [decoder decodeObjectForKey:@"author"]; self.pageCount = [decoder decodeIntegerForKey:@"pageCount"]; self.categories = [decoder decodeObjectForKey:@"categories"]; self.available = [decoder decodeBoolForKey:@"available"]; return self; } - (void)encodeWithCoder:(NSCoder *)encoder { [encoder encodeObject:self.title forKey:@"title"]; [encoder encodeObject:self.author forKey:@"author"]; [encoder encodeInteger:self.pageCount forKey:@"pageCount"]; [encoder encodeObject:self.categories forKey:@"categories"]; [encoder encodeBool:[self isAvailable] forKey:@"available"]; } @end 如上,NSCoding 主要是样板文件。每个属性用属性名作为key,编码或解码成一个对象或者类型。(有些开发者喜欢定义NSString *常量用作keypath, 其实通常这是没必要的) 但是在控制整个序列化过程中样板文件有时候也是非常有用的东西,它可以保持灵活,可以这样解释: Migrations: 如果一个数据模型发生变化,如添加,重命名或删除一个字段,这应该与之前序列化的数据保持兼容性。Apple提供了一些参考"Forward and Backward Compatibility for Keyed Archives". Archiving non-NSCoding-compatible Classes: 根据面向对象设计原则,对象应该可以被编码和解码成一种序列化的格式。但是如果一个类不是内置遵循NSCoding,你可以后续让这个类遵循NSCoding来达到目的。 Mantle是一个意在减少写NSCoding样板文件的类库。如果你正在寻找更方便使用NSCoding代替Core Data创建model的方法,那Mantle值得一看。 当然,序列化只是故事的一部分。决定把数据持久化到什么地方又是另一个问题。同样,这里有两个方法:写入本地文件系统或者使用NSUserDefaults。 File System NSKeyedArchiver 和 NSKeyedUnarchiver 提供了很方便的API把对象读取/写入磁盘。 一个基于NSCoding的table view controller可以通过file manager设置它的属性集合。 Archiving Objective-C [NSKeyedArchiver archiveRootObject:books toFile:@"/path/to/archive"]; Unarchiving Objective-C [NSKeyedUnarchiver unarchiveObjectWithFile:@"/path/to/archive"]; NSUserDefaults 每个应用程序都有自己的user preferences,它可以存储和检索遵循NSCoding协议的对象或者是C类型数据。 然而不推荐将整个对象图存入NSUserDefaults,但是用这种方式编码复合对象是不错的选择,例如“当前用户”的对象或者API credentials(用 Keychain 来代替)。 Archiving Objective-C NSData *data = [NSKeyedArchiver archivedDataWithRootObject:books]; [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"books"]; Unarchiving Objective-C NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"books"]; NSArray *books = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 作为开发者,我们是有义务去理解我们应用程序的目标和需求,并且抑制住过于工程化和过早优化的冲动。 在应用程序中使用Core Data的决定或许是显而易见的。但是在很多情况下,Core Data 被发现是如此的笨拙或者不必要的,甚至是一种对可用性的障碍,更不用说实用性。 即使很多应用在某些方面可能受益于Core Data,让事物从简单演化到复杂是必要的,其中蕴含着智慧。但是就持久化而言,它不会比NSCoding更简单。 作者 Mattt ThompsonMattt Thompson Mattt Thompson (@mattt) is the creator & maintainer of AFNetworking and other popular open-source projects, including Postgres.app, ASCIIwwdc and Nomad. 翻译者 Yu Jin 下一篇文章 Core Data Libraries & Utilities 上周,我们感觉Core Data有些难,所以为了NSHipster的这个问题,我们将奉上关于使用Core Data的最好开源库的引导。仔细阅读,看看你如何充分利用这次Core Data体验。 相关文章 NSCharacterSet UIPrintInteractionController NSDateComponents NSCache 除非另有声明、本网站采用知识共享「署名-非商业性使用 3.0 中国大陆」许可协议授权。 本站文章由 Croath Liu 、 、 Delisa Mason 、 Jack Flintermann 、 Mattt Thompson 、 、 Mike Lazer-Walker 、 Natasha Murashev 和 Nate Cook 撰写、 Andrew Yang 、 April Peng 、 Bob Liu 、 Candyan 、 Chester Liu 、 Croath Liu 、 David Liu 、 GWesley 、 Henry Lee 、 JJ Mao 、 Lin Xiangyu 、 Ricky Tan 、 Sheldon Huang 、 Tiny Tian 、 Tony Li 、 Yifan Xiao 、 Yu Jin 和 Zihan Xu 翻译。
Embed this episode
Ready to play
399. nshipster-NSCoding : NSKeyedArchiver
No transcript for this episode yet
Similar Episodes
No similar episodes found.
Similar Podcasts
No similar podcasts found.