资料iOS学习

EOC 笔记 二(1)

2017-03-03  本文已影响8人  Mokyz

二、对象、消息、运行期(1)


6、理解『属性』这一概念

@interface EOCPerson : NSObject {
      @public
          NSString *_firstName;
          NSString *_lastName;
      @private
          NSString *_someInternalData;
}
@end;

这种写法的问题是:对象布局在编译器就已经固定了。只要是访问_firstName变量的代码,编译器就把其替换为『偏移量 offset』,这个偏移量是『硬编码』,表示该变量距离存放对象的内存区域的起始位置有多远。这样的话,如果在_firstName前又添加一个变量NSDate *_dateOfBirth;,那么原来_firstName的偏移量现在会指向_dateOfBirth,会读取到错误的值。所以这种写法在修改了类定义之后必须重新编译,以确保编译器计算正确的偏移量,倘若两份代码一份使用旧的类定义,一份使用新的,就会出现不兼容的现象。

// 通过属性定义类的的实例变量
@interface EOCPerson : NSObject {
@property NSString *firstName;
@property NSString *lastName;
}
@end;
// 对于使用者来说, 以上代码等同于:
@interface EOCPerson : NSObject {
- (NSString*)firstName;
- (void)setFirstName:(NSString*)firstName;
- (NSString*)lastName;
- (void)setLastName:(NSString*)lastName;
}
@end;
@property (nonatomic, getter=isOn) BOOL on;
// 使用时
switch.isOn;
  - **setter=<name>** 不常见。
@property (copy) NSString *name;
- (id)initWithName:(NSString *)name;

初始化方法的实现可以这样写:

- (id)initWithName:(NSString *)name
{
        if(self = [super init]) {
            _name = [name copy];
        }
        return self;
}

为什么这里不直接调用setter方法呢?第7条会做详细解释。


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


8、理解『对象等同性』这一概念

- (BOOL)isEqual:(id)object;
- (NSUInteger)hash;

这两个方法的默认实现是:当且仅当其『指针值(或内存地址)』完全相等时,这两个对象才相等。若要在自定义对象中重写这两个方法,则必须保证:如果isEqual方法判断两个对象相等,则 hash方法也必须返回相同的值。但是如果hash返回相同的值,那么isEqual方法未必认为两个对象相等。一种较好的计算 hash 值的方式:

// 以前面提到的 EOCPerson 类为例:
- (NSUInteger)hash {
        NSUInteger firstNameHash = [_firstName hash];
        NSUInteger lastNameHash = [_lastName hash];
        NSUInteger ageHash = _age;
        return firstNameHash ^ lastNameHash ^ ageHash;
}

9、以『类族模式』隐藏实现细节

if ([maybeAnArray class] == [NSArray class]) {
      // do someting
}

应当使用类型信息查询方法

if ([maybeAnArray isKindOfClass:[NSArray class]]) {
      // do someting
}

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

关联类型 等效@property中的
OBJC_ASSOCIATION_ASSIGN assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC nonatomic,retain
OBJC_ASSOCIATION_COPY_NONATOMIC nonatomic,copy
OBJC_ASSOCIATION_RETAIN retain
OBJC_ASSOCIATION_COPY copy

下列方法可以管理关联对象:

// 设置对象value为object 的键为*key, 存储策略为 policy 的关联对象
- void objc_setAssociatedObject (id object, void *key, id value, objc_AssociatedPolicy policy) 
// 获取object对象中的键为 *key 的关联对象值.
- id objc_getAssociatedObject (id object, void *key) 
// 移除 object 的所有关联对象
- void objc_removeAssociatedObject(id object)
上一篇下一篇

猜你喜欢

热点阅读