当前位置:网站首页>[OC study notes] attribute keyword
[OC study notes] attribute keyword
2022-07-30 18:00:00 【Billy Miracle】
@property
@property关键字可以自动生成某个成员变量的setter和getter的声明.@synthesize关键字会指定一个以下划线 ( _ ) 为前缀,Plus the attribute name(例如_<name>)的成员变量. 并且由编译器自动进行该属性setter和getter的实现.@dynamic关键字,The compiler will not automatically synthesize accessor methods,generally used to givecategory添加属性的时候.
注意,Category cannot add member variables,But attributes can be added,从底层原理来说:分类是在运行时去把分类中的方法添加到类的方法列表里,类的底层其实是结构体,分类可以添加属性,不能添加成员变量,因为结构体声明后不能加成员,而属性是结构体里的一个列表(rw:property_array_t / ro: property_list_t),就是可以加的.
正确的做法是我们通过手动的实现setter/getter,通过关联对象绑定属性值到分类上.
默认设置
- 基本数据类型:
atomic,readwrite,assign - 对象类型:
atomic,readwrite,strong
属性关键字
| 分类 | 属性关键字 |
|---|---|
| 原子性 | atomic、nonatomic |
| 读写权限 | readwrite、readonly、setter、getter |
| 内存管理 | assign、weak、unsafe_unretained、retain、strong、copy |
| 可空性 | (nullable、_Nullable 、__nullable)、(nonnull、_Nonnull、__nonnull)、(null_unspecified、_Null_unspecified 、__null_unspecified)、null_resettable |
原子性
| 属性关键字 | 用法 |
|---|---|
| atomic | 原子性(默认),编译器会自动生成互斥锁,对 setter 和 getter 方法进行加锁,可以保证属性的赋值和取值的原子性操作是线程安全的,但不包括操作和访问.比如说 atomic 修饰的是一个数组的话,那么我们对数组进行赋值和取值是可以保证线程安全的.但是如果我们对数组进行操作,比如说给数组添加对象或者移除对象,是不在 atomic 的负责范围之内的,所以给被 atomic 修饰的数组添加对象或者移除对象是没办法保证线程安全的. |
| nonatomic | 非原子性,一般属性都用 nonatomic 进行修饰,因为 atomic 非常耗时. |
读写权限
| 属性关键字 | 用法 |
|---|---|
| readwrite | 可读可写(默认),同时生成 setter 方法和 getter 方法的声明和实现. |
| readonly | 只读,只生成 getter 方法的声明和实现. |
| setter | 可以指定生成的 setter 方法名,如 setter = setName. |
| getter | 可以指定生成的 getter 方法名,如 getter = getName. |
内存管理
| 属性关键字 | 用法 |
|---|---|
| assign | 1. 既可以修饰基本数据类型,也可以修饰对象类型; 2. setter 方法的实现是直接赋值,一般用于基本数据类型 ; 3. 修饰基本数据类型,如 NSInteger、BOOL、int、float 等; 4. 修饰对象类型时,不增加其引用计数; 5. 会产生悬垂指针(悬垂指针:assign 修饰的对象在被释放之后,指针仍然指向原对象地址,该指针变为悬垂指针.这时候如果继续通过该指针访问原对象的话,就可能导致程序崩溃). |
| weak | 1. 只能修饰对象类型; 2. ARC 下才能使用; 3. 修饰弱引用,不增加对象引用计数,主要可以用于避免循环引用; 4. weak 修饰的对象在被释放之后,会自动将指针置为 nil,不会产生悬垂指针. |
| unsafe_unretained | 1. 既可以修饰基本数据类型,也可以修饰对象类型; 2. MRC 下经常使用,ARC 下基本不用; 3. 同 weak,区别就在于 unsafe_unretained 会产生悬垂指针. |
| retain | 1. MRC 下使用,ARC 下基本使用 strong; 2. 修饰强引用,将指针原来指向的旧对象释放掉,然后指向新对象,同时将新对象的引用计数加1;3. setter 方法的实现是 release 旧值,retain 新值,用于OC对象类型. |
| strong | 1. ARC 下才能使用; 2. 原理同 retain; 3. 但是在修饰 block 时,strong 相当于 copy,而 retain 相当于 assign. |
| copy | setter 方法的实现是 release 旧值,copy 新值,用于 NSString、block 等类型. |
所有权修饰符
| 所有权修饰符 | 用法 |
|---|---|
| __strong | 1. 强引用持有对象,可以对应 strong、retain、copy 关键字. 2. 编译器将为 strong、retain、copy 修饰的属性生成带 __strong 所有权修饰符的实例变量. |
| __weak | 1. 弱引用持有对象,对应 weak 关键字,ARC下用来防止循环引用. 2. 编译器将为 weak 修饰的属性生成带 __weak 所有权修饰符的实例变量. |
| __unsafe_unretained | 1. 弱引用持有对象,对应 unsafe_unretained、assign 关键字,MRC下用来防止循环引用. 2. 编译器将为 unsafe_unretained 修饰的属性生成带 __unsafe_unretained 所有权修饰符的实例变量. 3. 与 __weak 相比,它不需要遍历 weak 表来检查对象是否 nil,性能上要更好一些.但是它会产生悬垂指针. |
| __autoreleasing | 在 MRC 中我们可以给对象发送 autorelease 消息来将它注册到 autoreleasepool 中,而在 ARC 中我们可以使用 __autoreleasing 修饰符修饰对象将对象注册到 autoreleasepool 中. |
一些问题
Q:atomic 修饰的属性是怎么样保存线程安全的?
答: 编译器会自动生成互斥锁,对
setter和getter方法进行加锁,可以保证属性的赋值和取值原子性操作是线程安全的,但不包括操作和访问.比如说atomic修饰的是一个数组的话,那么我们对数组进行赋值和取值是可以保证线程安全的.但是如果我们对数组进行操作,比如说给数组添加对象或者移除对象,是不在atomic的负责范围之内的,所以给被atomic修饰的数组添加对象或者移除对象是没办法保证线程安全的.
Q:什么时候使用 weak/__weak 关键字?
答:ARC 中为了避免循环引用而使用,可以让相互引用的对象中的一个使用
weak/__weak弱引用修饰,常用于对delegate和block的修饰;
Q:assign 和 weak 关键字的区别有哪些?
weak只能修饰对象,而assign既可以修饰对象也可以修饰基本数据类型;assign修饰的对象在被释放后,指针仍然指向原对象地址;而weak修饰的对象在被释放之后会自动置指针为nil;- 相同点:在修饰对象的时候,
assign和weak都不改变对象的引用计数.
Q:以下代码会出现什么问题?(深浅拷贝)
@property (copy) NSMutableArray *array;
答:不论赋值过来的是
NSMutableArray还是NSArray对象,进行copy操作后都是NSArray对象(深拷贝).由于属性被声明为NSMutableArray类型,就不可避免的会有调用方去调用它的添加对象、移除对象等一些方法,此时由于copy的结果是NSArray不可变对象,对NSArray对象调用添加对象、移除对象等方法,就会产生程序异常.
边栏推荐
猜你喜欢

Mathematical Principles of Graph Convolutional Neural Networks——A Preliminary Study on Spectral Graph Theory and Fourier Transform

银行适用:此文能够突破你的运维流程管理问题

Py程序员的七夕情人节

Error EPERM operation not permitted, mkdir 'Dsoftwarenodejsnode_cache_cacach Two solutions

leetcode-1319:连通网络的操作次数

高级语言垃圾回收思路和如何减少性能影响原理分析

JMeter Notes 4 | JMeter Interface Introduction

Linux-安装MySQL(详细教程)

宝塔搭建PHP自适应懒人网址导航源码实测

FastJson反序列化漏洞(复现)
随机推荐
分账系统二清解决方案如何助力电商平台合规经营?
数据库系统原理与应用教程(069)—— MySQL 练习题:操作题 95-100(十三):分组查询与聚合函数的使用
2022鹏城杯web
Py程序员的七夕情人节
LayaBox---TypeScript---变量声明
Prometheus 基本概念
论文阅读之《Quasi-Unsupervised Color Constancy 》
Leetcode数据库系列题解合集(持续更新)
What are the applications of X-rays?
Kettle--MySQL生产数据库千万、亿级数据量迁移方案及性能优化
【牛客编程题】GO语言入门46题
Dodging ice cream assassins?Crawling ice cream prices through crawlers
如何让 JOIN 跑得更快?
高性能短链设计
LayaBox---TypeScript---类
银行适用:此文能够突破你的运维流程管理问题
windwons 下GPU环境和pytorch安装
Vulkan与OpenGL对比——Vulkan的全新渲染架构
MySQL【单行函数】
基于MATLAB的电力系统短路故障分析与仿真