Objective-C:延迟加载模型模式

时间:2014-09-27 14:23:02

标签: objective-c design-patterns

我有对象,更确切地说是模型,其中一些属性是懒惰加载的,即从服务器读取时。目前,我运用经典技术,例如

@synthetize description = _description;
- (NSString *)description {
    if (!_description) {
        NSError *error = nil;
        _description = [NSString stringWithContentsOfURL:url 
                                 encoding:NSUTF8StringEncoding
                                 error:&error];
        if (error) {
            _description = nil;
            // error handling
        }
    }
    return _description;
}

然而,它涉及大量代码重复。当然,我仍然可以使用通用方法来执行此操作并在所有getter中调用此方法(这就是我所做的)。但你有更好的主意吗?

编辑:按照评论中的建议使代码更安全。这是另一个建议:

@synthesis description = _description;
- (NSString *)descriptionWithCompletion:(void (^)(NSString *description, NSError *error))completion {
    if (!_description) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSError *error = nil;
            _description = [NSString stringWithContentsOfURL:url 
                                     encoding:NSUTF8StringEncoding
                                     error:&error];
            if (error) _description = nil;

            completion(_description, error);

         });
    }
    completion(_description, nil);
}

1 个答案:

答案 0 :(得分:0)

所以,你试图减少像这样的方法的样板:

- (NSString *)prop {return [self _genericGetterForProperty:_prop];}

使用宏是一种选择;它会减少文本的数量,但是你仍然需要为每种方法提供一条线,所以我不清楚它是否真的值得额外的复杂性。

有一种方法可以通过dynamic method resolution完成此操作。基本上,您在课堂上实施+ resolveInstanceMethod:。如果有人试图在模型对象上调用您在编译时未提供的方法,则会调用它。您可以实现它来检查传递的选择器,看它是否与您的xxxWithCompletion:结构匹配。如果是,您可以基于“xxx”值构建实现并将其添加到您的类中。您可以通过将属性声明为@dynamic或通过编译指示明确禁止警告来阻止编译器向您发出警告。

但是,我不推荐它。这是一个复杂而棘手的解决方案;除非你有数百个属性,否则我只会编写样板文件。 (或者编写一个脚本来编写样板文件。)