前言

Effective Objective-C 2.0 系列读书笔记最后一篇

笔记

理解“属性”这一概念

  1. 下面两部分代码等效

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @interface EOCPerson : NSObject
    @property NSString *firstName;
    @end

    @interface EOCPerson : NSObject {
    NSString *_firstName;
    }
    - (NSString *)firstName;
    - (void)setFirstName:(NSString *)firstName;
    @end

    可以理解成:属性 = 实例变量 + 存取方法

  2. 可以改变属性生成的实例变量的名字:

    1
    2
    3
    @implementation EOCPerson
    @synthesize firstName = _myFirstName;
    @end

    将实例变量命名成_myFirstName ,不再使用默认的名字

  3. 当然还可以不让编译器自动生成存取方法,就是使用dynamic

    1
    2
    3
    @implementation EOCPerson
    @dynamic firstName;
    @end

    此时不会自动生成存取方法,也不会自动创建实例变量。在编译访问属性的代码时,也不会出错,因为编译器相信能在运行期找到对应的方法

  4. 具备readonly特性的属性仅拥有获取方法,只有当该属性由@synthesize实现时,编译器才会为其合成获取方法

  5. 拥有与非拥有 是针对指针与内存空间来说的:

    1
    @property (nonatomic, strong) NSString *strPointer;

    上面的语句说明:有一个NSString指针,如果他指向一块存放NSString的内存,那么strPointer指针拥有该内存。该内存的reference count加1

  6. copy 对于NSString来说特别有用,特别是在NSString和NSMutableString之间转换的时候。需要注意的是在初始化方法中,初始化该属性也要使用copy方法

    1
    2
    3
    4
    5
    6
    - (id)initWithFirstName:(NSString *)firstName {
    if (self = [super init]) {
    _firstName = [firstName copy];
    }
    return self;
    }
  7. 不应该在init方法中调用存取方法。

  8. iOS中的同步锁性能开销较严重,所以一般使用的nonatomic属性

在对象内部尽量直接访问实例变量

  1. 直接访问实例变量和通过存取方法来访问的区别
    1. 直接访问不经过方法派发,速度更快
    2. 直接访问时不会经过设置方法,绕过了内存管理语义。例如:在ARC下直接方法一个copy属性,那么不会拷贝该值,只会retain
    3. 直接访问不会触发KVO
  2. 折中的方案:设置时使用设置方法,读取时直接访问

理解“对象等同性”这一概念

  1. 应该使用NSObject协议中的isEqual方法来判断对象的等同性。可以对象自己实现isEqual来精确判断
  2. 当然对于特殊的对象可以使用更精确的方法

以“类族模式”隐藏实现细节

  1. UIButton有一个类方法:+ (UIButton *)buttonWithType:(UIButtonType)type; 该方法返回的对象类型根据type不同而不同,但是基类都是UIButton
  2. 类族的基类一般没有 init 方法,提示用户:这种类不需要用户自己去创建。
  3. 调用isMemberOfClass:的时候不会返回YES,因为不是UIButton,只是它的子类
  4. NSArray就是类族

在既有类中使用关联对象存放自定义数据