1

我的代码(尤其是当我更多地了解TDD时)有很多延迟加载的属性,例如:

@interface MyClass ()

@property (nonatomic, strong) MyFoo *myFoo;

@end

@implementation MyClass

- (MyFoo *)myFoo {
   if (!_myFoo) {
     _myFoo = [MyFoo alloc] sharedFoo]; // or initWithBar:CONST_DEF_BAR or whatever
   }
   return _myFoo;
}

@end

或者,更好的线程安全版本:

- (MyFoo *)myFoo {
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    _storeHelper = [SHStoreHelper sharedStoreHelper];
  });
}

我有点希望 Apple 将其作为属性的一个方面进行自动代码生成,例如:

@property (lazyload) MyFoo *myFoo;

不过,除此之外,我希望有一个用于实现位的宏,例如

#define LAZY_ALLOC(x, y, _y, a, i) -(x *)y { if (!_y) { _y = [[x a] i]; } return _y }

然后不是你刚刚拥有的常规方法实现

LAZY_ALLOC(MyClass, myClass, _myClass, alloc, init)

这对于想要的课程来说足够灵活

LAZY_ALLOC(OtherClass, otherClass, _otherClass, sharedClass, nil)

或者

LAZY_ALLOC(OtherClass, otherClass, _otherClass, alloc, initWithFrame:SOME_FRAME)

1) 预处理器需要_y。有没有办法让它构造_autosynthesized ivar而不单独传递它?2)这有大问题吗?对我来说,它提高了可读性,因为它本质上说“哦,又是那个东西”比完全写出来的版本更快 3)你认为它的风格很恶心吗?风格上很棒吗?

4

2 回答 2

3

我想你想要的是##。你可以把它写成:

#define LAZY_ALLOC(type, name, initialValue) \
    -(type *)name { \
        static dispatch_once_t onceToken; \
        dispatch_once(&onceToken, ^{ \
            if (! _ ## name) { \
                _ ## name = (initialValue); \
            } \
        } \
        return _ ## name; \
    }

编辑:

需要明确的是,我不会在单例的sharedInstance-type 方法之外使用这个特殊的习惯用法进行延迟加载。由于静态 dispatch_once_t,此代码只会对每个类(而不是每个实例)执行一次延迟加载。我只是从问题中复制代码并将其转换为宏模板来说明该技术,但我觉得我应该澄清这一点。

就个人而言,对于延迟加载普通实例变量,我会使用非线程安全版本,如果您需要线程安全,则只需切换到急切加载或专门处理这种情况。有一些技术可以将延迟加载与访问器中的线程安全相结合,但是:

  1. 他们相当慢。

  2. 很少同时真正需要两者。

  3. 除了在访问器方法中添加互斥锁之外,您可能还需要为线程安全做一些特殊的架构设计。

所以我不会将这种情况合并到标准模板宏中。

于 2012-12-17T22:44:52.553 回答
0

写一个方法+(id) lazyLoad:(Class)class sharedPointer:(NSObject**)ptrAddr或类似的东西。使其成为 LazyLoader 类的方法,该类只实现该方法。

要使用它:

- (MyFoo *)myFoo {
    return [LazyLoader lazyLoad:[MyFoo class] sharedPointer:&_myFoo];
}

可能需要在 sharedPointer parm 上添加一些 ARC 甜味剂,但基本上这应该可以工作,并且可以按照您的意愿(如果您愿意的话)使其成为线程安全的。

(我将把它作为练习留给读者了解如何使用替代的 init 方法。)

于 2012-12-17T22:40:14.700 回答