第六七八条:属性相关

在Java或C++中,对象布局在编译器(compile time)已经固定了,对象的关于成员变量的代码被编译器替换为“偏移量(offset)”,这个偏移量是“硬编码(hardcode)”,表示这个变量距离存放对象的内存区域的起始地址有多远。这种情况下,如果修改类定义之后就必须重新编译,否则就会出错。

OC在这方面的优化是,把实例变量当做是一种存储偏移量所用的“特殊变量(special variable)”,交由类对象(class object)保管。偏移量会在运行期查找,如果类的定义变了,那么存储的偏移量也就变了,这样的情况下,无论何时访问实例变量总能够使用到正确的偏移量。还可以在运行期向类中添加新的实例变量。

使用@property语法定义属性 编译器会自动写出一套存取方法,用以访问给定类型中具有给定名称的变量。在此之外,编译器还会向类中添加适当类型的实例变量,并且在属性前添加下划线,以此作为实例变量的名字。

编译器会把“.”点语法转化为对存取方法的调用。

属性的修饰关键字:

1.原子性: nonatomic/atomic 

由编译器所合成的方法会通过锁定机制确保其原子性atomic,如果自己定义存取方法,注意些和属性的原子性相符的代码。

但是我们一般把属性都声明为nonnatomic,因为在iOS开发中,使用同步锁的开销比较大,会带来性能的问题,如果要实现“线程安全”的操作,还需要采取更为深层的锁定机制才行。

2.读写权限:readwrite(读写)/readonly(只读)

readwrite的属性拥有getter、setter方法;readonly的属性只有getter方法;

3.内存管理:assign / strong / weak / unsafe_unretained / copy

assign:只会对基本纯量类型CGFloat,NSInteger等进行简单的赋值;

strong:定义了一种拥有关系,设置新值时,会保留新值,释放旧值,然后将新值设置上去;

weak:定义了一种非拥有关系,设置新值时,不保留新值,也不保留旧值,在属性所指的对象释放时,属性值会清空;

unsafe_unretained:相当于是对象类型的assign,在属性所指的对象释放时,属性值不会清空;

copy:定义了一种拥有关系,但是设置新值时,不会保留新值,而是将其拷贝。

4.方法名:getter=<name>  setter=<name>

 getter=<name> 指定设置方法的方法名

setter=<name>  指定获取方法的方法名

在对象内部读取实例变量的时候,用直接访问的形式;设置实例变量的时候通过属性来做。

直接访问实例变量,编译器会直接访问保存对象实例变量的那块内存;并且不会调用其设置方法(setter),这样就绕过了属性定义的“内存管理语句”;也不会触发“键值观察KVO”。

但是在初始化方法中应该直接访问实例变量;在懒加载中应该使用属性,来通过setter方法访问实例变量。

 

对象的等同性:

当比较两个对象是否相等的时候,如果我们使用"=="来比较的话,比较的将是两个对象的指针,如果这两个指针指向同一个地址才相等,否则是不相等的。这显然和我们所想的不符合,我们就可以通过重写NSObject的"isEqual:",来书写我们自己的判断逻辑。比如说NSString类实现了自己的对比方法"isEqualToString"。

NSObject类中有两个可以判定两个对象是否具有等同的关键方法:

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

如果两个对象通过isEqual判定相等,那么两个对象返回的hash值必须是同一个值;

相反,如果两个对象的hash返回值是同一个值,isEqual判断可以不相等。

当我们写对象的同等性判断时,应该重写isEqual方法,如果被检测参数和接受该消息的对象都属于同一个类的话,就调用自己编写的判定方法,否则就交由超类来判断。

举个例子:

//假设类名为 myclass  有两个NSString属性 name  age 
- (BOOL)isEqualToMyclass:(myclass)cls{
    if(self == cls) return YES;
    if(![_name isEqualToString:cls.name]){
        return NO;
}
    if(![_age isEqualToString:cls.age]){
        return NO;
}
    return YES;
}


- (BOOL)isEqual:(id)object{
    if([self class] == [object class]){
        return [self isEqualToMyclass:(mycalss*)object];
}else
    return [super isEqual:object];
}
//推荐计算hash的方法
//如果属性过多 不要盲目的去检测每一个属性 要根据实际情况来区分
//编写hash方法时,应该使用计算速度快且碰撞几率低的算法
- (NSUInteger)hash{
    NSUInteger nameHash = [_name hash];
    NSUInteger ageHash= [_age hash];
    return nameHash^ageHash;

}

有一点要注意的是,如果放对象放入数组、字典、集合中后,又改变了该对象,可能会出现问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值