iOS 更懒的懒加载

懒加载是什么就不多介绍了

OC 里面是怎么写懒加载的呢?

假设我有一个 nameLabel 属性

- (UILabel *)nameLabel {
    if (!_nameLabel) {
        _nameLabel = [UILabel new];
        // ......自定义代码
    }
    return _nameLabel;
}

问题

还行还行,很简单的写法

但是,如果一个类里面充满了大量的属性,并且都想写成懒加载,在我看来有很多碍眼的代码,而且还得自己浪费精力写

  • if () {}
  • ! _ (感叹号、下划线,要两个手指打)
  • return

干了多年的 iOS,如今我才真正的开始写大量的原生代码,开始体验到了懒加载的美妙,不过懒加载的代码实在让我眼睛痛。

所以经过提取公共代码的方式,我抽出了一个简便的... (方法?啪!想什么呢?不可能抽出硬编码方法的) ... 只能使用宏定义来简化懒加载的写法,本质和原来一模一样

LazyLoad 1.0

#define GGLazyLoad(Type, Name, Code) \
- (Type)Name { \
    if (!_##Name) { \
        Code; \
    }\
    return _##Name; \
}

#define GGLazyLoadNew(TypeNoPoint, Name, Code) \
- (TypeNoPoint *)Name { \
    if (!_##Name) { \
        _##Name = [TypeNoPoint new]; \
        Code; \
    }\
    return _##Name; \
}

刚开始呢,我其实只用了 GGLazyLoad 这个宏,但后来发现很多对象创建也不过就是执行 new 方法而已,所以又定义了一个 GGLazyLoadNew 宏,把 new 操作省了,顺带连指针符号(*)都省得写了,太棒了。

但是在使用过程中,我遇到了令人头疼的问题,宏的代码块里面,不能写静态的数组、字典等内容。


代码块里面无法使用数组

LazyLoad 2.0

直到我看到 FDTemplateLayoutCell 的源码,看到 FDIndexPathHeightCache 里面有这么一个宏 FDPrimaryCall(...)

好奇心使我尝试了一下,神奇的发现它竟然可以在代码块里面写数组,于是研究了下,终于可以愉快的让所有懒加载都用上这个方便的宏了,实在是太感动了,感谢 Sunny 大神啊

先来看看对比效果


对比

我承认我夸大了,实际的代码中肯定会有大量的换行,两边的实际代码量,不会有这样两倍的差距。

阿勒,被你们发现了,改进的宏不止加入了数组字典的支持,还加入了一个简短的临时变量 z, 可以让代码更简洁。不过按个人喜好,想用下划线变量也是可以的。

LazyLoad 最终版 !!!

#define GGLazyLoad(TypeNoPoint, Name, Code...) \
- (TypeNoPoint *)Name { \
    if (!_##Name) { \
        TypeNoPoint *z = nil; \
        Code; \
        _##Name = z; \
    }\
    return _##Name; \
}

#define GGLazyLoadNew(TypeNoPoint, Name, Code...) \
- (TypeNoPoint *)Name { \
    if (!_##Name) { \
        TypeNoPoint *z = [TypeNoPoint new]; \
        Code; \
        _##Name = z; \
    }\
    return _##Name; \
}

问题

当然了,这个宏定义并不是完美的,它有些无法解决问题

  1. 代码块里面的代码,着色不够完美
  2. show document items(ctrl+6)这个列表里面,无法显示懒加载方法
  3. 还有无法断点调试
编辑器的问题

还有的问题,比如宏用多了影响编译速度啊,我觉得不太大,文件编译后都会有缓存。

最后,都 2020 年了,还在这里折腾 OC 是不是太落后了 。

// Swift 
lazy var nameLabel: UILabel = {
    let z = UILabel.init()
    return z
}()

你可能感兴趣的:(iOS 更懒的懒加载)