iOS property关键字详解

栏目: IOS · 发布时间: 5年前

内容简介:补充atomic是自旋锁,即当上一线程没有执行完毕(被锁住),下一线程会一直等待(不会进入睡眠状态),当上一线程执行完毕,下一线程立即执行。他区别于互斥锁,互斥锁在等待的时候,会进入睡眠状态,当上一个线程执行完毕,睡眠状态就会被唤醒,然后再执行。

property 属性关键字我们在日常的开发中经常会用到,所以我们有必要对其有充分的了解,这样对于我们日常开发使用时就能做到知其所以然。 ####property关键字介绍 property 关键字分为四类:

  1. 原子性: atomicnonatomicproperty 中默认是 atomic ,也就是线程安全,但是我们一般使用的是 nonatomic 。因为 atomic 的线程安全系统资源开销相对较大,影响性能,即使我们需要使用线程安全,我们也可以使用其他方法实现。atomic实现原理是在 gettersetter 中使用 @synchronized 同步锁关键字进行代码块锁定而实现的。

补充atomic是自旋锁,即当上一线程没有执行完毕(被锁住),下一线程会一直等待(不会进入睡眠状态),当上一线程执行完毕,下一线程立即执行。他区别于互斥锁,互斥锁在等待的时候,会进入睡眠状态,当上一个线程执行完毕,睡眠状态就会被唤醒,然后再执行。

  1. 引用计数相关: assignretainweakstrongcopy 、iOS5以前使用的 unsafe_unretainedassign :主要修饰基本数据类型,不能修饰对象类型,如 NSInterger , CGFloat 等类型。并且统一由系统栈进行内存管理。 retain :修饰对象类型,强引用对象,并是对象引用计数加1,可用于 MRC 环境中。 weak :修饰对象类型,对对象弱引用,不增加对象的引用计数。如果对象销毁了,指针会自动指向 nil ,所以可以防止野指针的问题。 strong :修饰对象类型,对对象强引用,会增加对象的引用计数。如果指向了空对象,会造成野指针。只能用于 ARC 环境。 copy :在一个新对象引用计数为1,赋值时对传入值进行一份拷贝,所以才使用copy关键字。你将一个对象赋值给一个属性,该属性并不会持有对象,而是会创建一个新对象,并将这个对象拷贝给它。使用 copy 关键字的对象必须实现 NSCoding 协议。 unsafe_unretained :跟 weak 类似,声明一个弱引用,区别是当引用计数为0时,变量不会自动设置为 nil

  2. 读写权限相关:默认是 readwrite (可读可写),还有readonly,修饰属性时,属性不能被外界修改。

  3. 方法名:可设置属性的 settergetter 方法名。 ####补充介绍 weak 关键字

  • 使用场景 用于一些对象互相引用时,避免出现互相强引用而导致的循环引用,对象不能释放的。
  • 实现原理 weak 修饰时, runtime 会维护一个 hash 表(也称为 weak 表),用于存储对象的所有 weak 指针, hash 表的 key 是该对象的地址, valueweak 指针的地址(这个地址的值是所指对象的地址)数组。(备注 strong 是通过 runtime 维护的一个自动引用计数表) weak 的实现原理总结:
  1. 初始化时, runtime 会调用 objc_initWeak 函数,初始化一个新的 weak 指针指向对象地址;
  2. 添加引用时, objc_initWeak 函数会调用 objc_storeWeak 函数, objc_storeWeak 的作用是更新指针指向,创建对应的弱引用表(hash表);
  3. 释放时,调用 clearDeallocating 函数。 clearDeallocating 函数首先根据对象地址获取 weak 指针地址的数组,然后遍历这个数组把其中指向空对象的指针设为 nil ,最后把这个指针从 weak 表中删除,最后清理对象的记录。

copystrong : 讲这两个字之前我们需要了解深复制和浅复制相关的只是,可以参考这里。具体示例如下:

@property (nonatomic, copy) NSMutableArray *mutArray;
NSMutableArray *mutArray1 = [NSMutableArray array];
self.mutArray = mutArray1;
复制代码

等同于

@property (nonatomic, strong) NSMutableArray *mutArray;
NSMutableArray *mutArray1 = [NSMutableArray array];
self.mutArray = [mutArray1 copy];
复制代码

经过测试之后我们知道使用copy修饰的 mutArray 数组,当调用它的 setter 方法,它会建立一个引用计数为1的新对象,然后释放旧对象。而 copy 修饰的属性赋值时经过 copy 其实已经变成了不可变数组。而使用可变数组的增、删、改、查函数是会发现找不到相关的实例方法而 crash

NSString 为什么用 copy 而不用 retain我们通过实例来看看:

@property (nonatomic, retain) NSString *string;
NSMutableString *string1 = [[NSMutableString alloc] initWithString:@"abc"];
self.string = string1;
[string1 appendString:@"123"];
NSLog(@"==============  %@ =========", self.string);
2019-06-19 17:08:58.114333+0800 ThinTableVIew1[96955:2656816] ==============  abc123 =========

复制代码

从打印的信息可以看到当改变 string1 的值时, self.string 的值也改变了。下面我们通过查看 string 属性 setter 方法的实现来探究一下原理:

@property (nonatomic, retain) NSString *string;

- (void)setString:(NSString *)string {
    if (_string != string) {
        [_string release];
        _string = [string retain];
        //相当于
        //[string retain];
        //_string = string;
    }
}
==================
@property (nonatomic, copy) NSString *string;

- (void)setString:(NSString *)string {
    if (_string != string) {
        [_string release];
        _string = [string copy];
    }
}
复制代码

我们可以知道:

  • 当使用 retain 修饰 string 时调用的是 _string = [string retain] ,这样只会增加string的引用,而 _string 指针和 string 是指向同一块内容。所以改变 string 的内容同样的会改变 _string 的内容。
  • 当使用 copy 修饰 string 时,当传入的对象是可变对象时,调用的是 [string copy] ;会创建一个新的对象赋值给 _string ,所以 _stringstring 不会互相干扰,而改变 string 的内容不会影响 _string

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Game Engine Architecture, Second Edition

Game Engine Architecture, Second Edition

Jason Gregory / A K Peters/CRC Press / 2014-8-15 / USD 69.95

A 2010 CHOICE outstanding academic title, this updated book covers the theory and practice of game engine software development. It explains practical concepts and techniques used by real game studios,......一起来看看 《Game Engine Architecture, Second Edition》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具