FDModel 2.0.0

FDModel 2.0.0

测试已测试
语言语言 Obj-CObjective C
许可 MIT
发布日期最后发布2015年5月

Reid Main维护。



FDModel 2.0.0

概述

FDModel 是一个为 Objective-C 设计的模型层,旨在极大地简化从远程对象(即 NSDictionary、NSString、NSValue)创建模型对象的过程。用户只需要在他们的 FDModel 子类中覆盖 remoteKeyPathsToLocalKeyPaths 方法来定义远程 key path 与本地 key path 的映射关系,所有这些本地 key path 的解析、转换和设置都将自动处理。

FDModel 的另一个主要好处是保证:如果使用标识符创建了 FDModel 的一个实例,那么在给定时间内存中只会存在该模型的一个实例。为了自动化此过程,用户只需要在他们的子类中覆盖 remoteKeyPathForUniqueIdentifier 方法。所有使用标识符创建的 FDModel 实例都将存储在一个弱引用缓存中,这确保了如果 FDModel 的任何实例被任何其他东西引用,它总是在内存中。在内存吃紧的情况下,此缓存将清除不再被任何东西引用的模型。

FDModel 还提供了在对象被设置在本地键路径之前将其转换的能力。例如,如果 FDModel 的一个子类有一个名为 'status' 的属性,并且用户想转换远程键路径解析的值,他们可以实现一个名为 'statusTransformer' 的方法,该方法返回一个 NSValueTransformer。当即将设置状态属性时,此转换器将自动使用。

默认情况下,所有 FDModel 对象只保存在内存中。模型对象可以保存到 FDModelStore 中,如果尝试创建具有相应标识符的模型,则自动从存储中读取已保存到模型存储的任何模型。

并发注意事项

FDModel 暴露了一个 NSRecursiveLock,它被 FDModel 以及 FDModelProviderFDModelStore(及其具体子类)内部使用,以确保对 FDModel 任何实例的修改都发生在单个线程上。如果您需要修改 FDModel 的任何属性,则建议在做出更改时利用此锁,并在 UI 线程之外进行操作。

这是为了防止在多个线程上访问可变模型,这通常会导致崩溃或其他不良行为(例如 https://devforums.apple.com/message/1079642)。

安装

FDModel 支持两种方法。这两种方法都假设您的 Xcode 项目正在使用模块。

1. 子项目

  1. 将 “FDModel” 项目添加到 “Framework Project” 目录作为子项目,或者将其添加到您的工作区。
  2. 将 "FDModel (iOS/Mac)" 添加到您的目标的 “Target Dependencies” 部分。
  3. 在将使用 FDModel 的任何文件中,使用 “@import FDModel”。

示例

以下是 "游戏" 模型对象的实现细节的简单示例。该项目包含了 iOS 和 Mac 示例项目,展示了如何从 NSDictionary 中实际创建这个游戏对象的实例。

FDGame.h

@interface FDGame : FDModel


@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *genre;
@property (nonatomic, copy) NSDate *releaseDate;


@end

FDGame.m

@implementation FDGame


+ (NSString *)remoteKeyPathForUniqueIdentifier
{
    return @"game_id";
}

+ (NSDictionary *)remoteKeyPathsToLocalKeyPaths
{
    FDGame *game = nil;

    NSDictionary *remoteKeyPathsToLocalKeyPaths = @{
        @"name" : @keypath(game.name), 
        @"genre" : @keypath(game.genre), 
        @"release_date" : @keypath(game.releaseDate)
        };

    return remoteKeyPathsToLocalKeyPaths;
}

+ (NSValueTransformer *)releaseDateTransformer
{
    FDValueTransformer *releaseDateTransformer = [FDValueTransformer registerTransformerWithName: @"ReleaseDateTransformer" 
        block: ^id(id value)
        {
            NSDateFormatter *dateFormatter = [NSDateFormatter new];
            dateFormatter.dateFormat = @"MM-dd-yyyy";

            NSDate *releaseDate = [dateFormatter dateFromString: value];

            return releaseDate;
        }];

    return releaseDateTransformer;
}

- (NSString *)description
{
    NSString *description = [NSString stringWithFormat: @"<%@: %p; id = %@; name = %@; genre = %@; release date = %@>", 
        [self class], 
        self, 
        self.identifier, 
        _name, 
        _genre, 
        _releaseDate];

    return description;
}

@end