iOS 中属性、实例变量 的选择

在我们一个项目中, 如果涉及多人开发,一般代码就会有多重风格,其中最明辨的,类的私有成员变量是如何定义的?

最常见的两种:

@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) UITableView *tableView;
@interface ViewController() {
    NSString *_name;
    UITableView *_tableView;
}

历史原因探索:

在 2011 年 ARC 被推出之前,Objective-C 是需要手工地管理引用计数的。
而对类的所有私有成员使用self.property的形式,就可以使编译器为我们自动生成管理引用计数的代码。
在 2012 年前,这个时候还需要使用@synthesize关键字来启用的。
于是,苹果通过在代码规范中推荐和强调使用self.property的编程习惯,来让大家避免在内存管理中遇到问题。

而在 ARC 时代,这个编程习惯带来的优势不再存在了,因为编译器会自动为我们管理引用计数,我们只需要关心不要造成循环引用问题就行了。

而我的问题:平常我们在 ViewController 中使用属性后,到底是直接用实例变量还是?点属性使用?

@property (nonatomic, strong) UILabel *nameLabel;

// 实例变量的写法
_nameLabel = [[UILabel alloc] init];
// 直接属性的写法
self.nameLabel = [[UILabel alloc] init];

大致的区别

  • 由于不经过 Objective-C 的方法派发,直接访问实例变量的实数当然是比较快的。
  • 直接访问实例变量的时候,不会调用其“设置方法”,这就绕过了为相关属性所定义的“内存管理语义啦”
  • 如果直接访问实例变量,不会触发 KVO。
  • 通过属性来访问有助于排查预支相关的错误,因为可以给“setter” 和 “getter”中新增断点,监控该属性的调用和访问的时间。

归纳基本原则

  • 在对象内部时,使用实例变量来读取;
  • 在写入数据是,则通过属性来写。
  • 在 初始化方法以及 dealloc 中一般都是获取实例变量来读写数据。
  • 懒加载的时候,设置肯定是实例变量,读取肯定是通过属性啦。

总的说来,在 ViewController 中无论使用哪一种风格,只要统一就好了,没有什么特别打的影响,但是我还是推荐在读取实例变量的时候采用直接访问的形式,设置实例变量的时候则通过属性来做。所以,我推荐在 ViewController 中使用self.property的风格,搭配懒加载的写法。

@property (nonatomic, strong) UILabel *nameLabel;

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.view addSubview:self.nameLabel];
    [self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(@100);
        make.leading.equalTo(@30);
        make.trailing.equalTo(@(-30));
        make.height.equalTo(@40);
    }];   
}

- (UILabel *)nameLabel {
    if (!_nameLabel) {
        _nameLabel = [[UILabel alloc] init];
    }
    return _nameLabel;
}

备注参考:

http://blog.devtang.com/2015/03/15/ios-dev-controversy-1/

你可能感兴趣的:(iOS 中属性、实例变量 的选择)