Objective-C Properties 详解
关于Objective-C 的property,很多iOS开发的新手都会很迷惑,也会包括有经验的iOS开发程序员,
因为Objective-C的property,说多不多,说少却也不少,从MRR(Manual Retain Release )到ARC模式,很多属性功能类似
名称却不一样,比如strony和retain,而且又牵扯到release, autorelease, alloc ,new,copy等一众函数,
所以看着很容被绕进去,迷失在这众多的property,
今天特地梳理支持ARC(iOS 5+) 的propterty的关键词:
strong, weak, copy, readonly/readwrite, atomic/nonatomic,assign,retain
由于strong和retain功能相同,所以会在最后总结的时候,比较所有的这些关键词异同点
1:定义一个property
如下,我们定义一个car 的interface, 该属性有一个property 为 brand(品牌)
// Car.h
#import <Foundation/Foundation.h> @interface Car : NSObject @property NSString *brand; @end
// Car.m #import "Car.h" @implementation car @synthesize brand = _brand; @end
2:属性的getter 和setter方法和synthesize
编译器会默认的为属性生成getter 和setter方法
- (NSString *)brand
{
return _brand;//_brand即使synthesize指定的属性名称
} - (void)setBrand:(NSString *)brand
{
_brand = brand;
}
注意:synthesize 不是必须明确声明,除非手动些属性的getter和setter方法
否则,complier默认生成的code 如下格式
@synthesize brand = _brand
synthesize关键字缺省方式是:将brand属性对应的实例便令声明为_brand,即_ + propertyname
当然可以自己指定比如brand = xxxbrand
编译器默认会将getter方法和属性同名,setter方法为set+属性(首字母大写),例如setBrand
可以指定属性的getter和setter方法名称
@property (nonatomic,getter=getBrand, setter = setBrand:)NSString *brand;
3:readonly和readwrite
声明 readonly属性
@property (readonly,getter=getBrand)NSString *brand;
声明了readonly的属性,一定没有setter方法,所以你可以使用getter或者 dot方法 获取属性的值,但肯定不可以使用
setter方法修改
Car *c = [[Car alloc]init];0 [c setBrand:@"tony"]; //Error NSLog(@"%@", [c getBrand]);
声明为readonly 不意味着我们不可以修改,propery 的accessor method 本来就是提供给其他接口调用的,
在我们内部,是直接操纵_brand实例的, 如下
// Car.h
- (void)setBrand:(NSString *)brand;
// Car.m
- (void )setBrand:(NSString *)brand;
{
_brand = brand;
}
readonly 对应的readwrite 属性, readwrite 是default的behavior,可以不显示声明
@property (readwrite)NSString *brand;
4:atomic, nonatomic
atomic 原子的,default behavior,支持多线程操作, 代价是开销比nonatomic大
如果声明一个属性,确定不会运行在多线程的环境,可以直接声明为nonatomic
@property (nonatomic)NSString *brand;
内存管理
Ojective-C 内存模型中,不管是MRR,还是ARC,都是根据对象的引用计数来确定对象是否回收
当对象的 引用计数为0,就会被回收(不一定是立即回收)
从引用计数的原理出发,Objective-C 提出了三种相关的是属性
strong, weak, copy
1:strony 属性
strong属性,即声明一个对象拥有另外一个对象,引用计数 + 1
加入 A对象 有个strong 属性的实例对象B, 则在A对象释放之前,B是不会释放的
看如下sample code
声明一个类Person,Person有一个属性name
//
// Person.h #import <Foundation/Foundation.h> @interface Person : NSObject @property (nonatomic) NSString *name; @end
// Person.m
#import "Person.h" @implementation Person - (NSString *)description
{
return self.name;
}
@end
声明一个Car 类,有两个属性 model和driver
// Car.h #import <Foundation/Foundation.h>
#import "Person.h" @interface Car : NSObject @property (nonatomic) NSString *model;
@property (nonatomic,strong) Person *driver; @end
main.m
// main.m
#import <Foundation/Foundation.h>
#import "Car.h"
#import "Person.h" int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *john = [[Person alloc] init];
john.name = @"John"; Car *honda = [[Car alloc] init];
honda.model = @"Honda Civic";
honda.driver = john; NSLog(@"%@ is driving the %@", honda.driver, honda.model);
}
return ;
}
可以看到,hoda对象对driver对象负责
2:weak属性
strong 属性,很直观的显示对象直接的关系,但也很容易引起内存泄露,
看如下代码,我们稍微小改了Person.h ,增加了Car 属性,
// Person.h
#import <Foundation/Foundation.h> @class Car; @interface Person : NSObject @property (nonatomic) NSString *name;
@property (nonatomic, strong) Car *car; @end
则在main.m
增加一行
john.car = honda;
则此时,john和hoda互相持有对方
二者这件形成了 retain cycle(互相持有的循环),就是典型的内存泄露的一种情况
如果car声明为weak,这个问题即迎刃而解
@property (nonatomic, weak) Car *car;
3:copy 属性
copy不同于strong, 并不拥有copy的对象,而是复制该对象(必须conform NSCopying
protocol )
sample code
#import <Foundation/Foundation.h>
#import "Car.h"
#import "Person.h" int main(int argc, char *argv[])
{ Car *bmw = [[Car alloc]init]; Person *driver = [[Person alloc]init]; NSMutableString *name = [NSMutableString stringWithFormat:@"zhangsan"];//mutable 的name 为zhangsan [driver setName:name];
[name setString:@"lisi"];//修改为lisi
[driver setCar:bmw]; [bmw setModel:@"X5"];
[bmw setDriver:driver]; NSLog(@"%@", [driver name]);//仍然是zhangsan }
copy 属性在被赋值的时候就copy了该值,所以即使该值是mutable的,属性的值也不会被修改,
现对于strong的持有对象,copy特别适合只是简单存储值得属性
以上都是ARC支持的属性。
4:属性retain
等同于 strong
5:unsafe_unretained
类似于weak,和weak不同的是,如果weak 属性指向的对象如果被销毁后,weak 属性被置为nil,
而 unsafe_unretained 不会,则又可能形成悬垂指针的问题
6:assign
默认的属性,不需要显示声明
指定setter方法进行简单的赋值 ,对基础数据类型(NSInteger,CGFloat)
和C数据类型(int, float, double, char)等等。
总结:
atomic //default
nonatomic
strong=retain //default
weak
assign //default
unsafe_unretained
copy
readonly
readwrite //default
引用:
http://rypress.com/tutorials/objective-c/properties
http://rypress.com/tutorials/objective-c/memory-management
http://stackoverflow.com/questions/8927727/objective-c-arc-strong-vs-retain-and-weak-vs-assign
Objective-C Properties 详解的更多相关文章
- log4j.properties 详解与配置步骤(转)
找的文章,供参考使用 转自 log4j.properties 详解与配置步骤 一.log4j.properties 的使用详解 1.输出级别的种类 ERROR.WARN.INFO.DEBUGERROR ...
- SpringBoot配置文件 application.properties详解
SpringBoot配置文件 application.properties详解 本文转载:https://www.cnblogs.com/louby/p/8565027.html 阅读过程中若发现 ...
- log4j.properties 详解与配置步骤
一.log4j.properties 的使用详解 1.输出级别的种类 ERROR.WARN.INFO.DEBUGERROR 为严重错误 主要是程序的错误WARN 为一般警告,比如session丢失IN ...
- [转]application.properties详解 --springBoot配置文件
本文转载:http://blog.csdn.net/lpfsuperman/article/details/78287265###; # spring boot application.propert ...
- application.properties详解 --springBoot配置文件【转载】
# spring boot application.properties配置的各个属性详解 # 该示例文件作为标准提供.(官方文档 翻译过来的) # 还是花了些功夫翻译,各位如果转发,请留下本文地址, ...
- application.properties详解 --springBoot配置文件
本文转载:http://blog.csdn.net/lpfsuperman/article/details/78287265###; # spring boot application.propert ...
- 转--log4j.properties 详解与配置步骤
一.log4j.properties 的使用详解 1.输出级别的种类 ERROR.WARN.INFO.DEBUGERROR 为严重错误 主要是程序的错误WARN 为一般警告,比如session丢失IN ...
- log4j.properties 详解与配置步骤总结
先提供一个项目中使用log4j.properties配置 #log4j.rootLogger=WARN, stdout, file log4j.rootLogger=INFO,console,dail ...
- 【转】log4j.properties 详解与配置步骤 - edward0830ly的专栏 - 博客频道 - CSDN.NET
一.log4j.properties 的使用详解 1.输出级别的种类 ERROR.WARN.INFO.DEBUGERROR 为严重错误 主要是程序的错误WARN 为一般警告,比如session丢失IN ...
- (转)spring hibernate properties详解
转载地址:http://blog.sina.com.cn/s/blog_692d0a650100xyqx.html Hibernate配置属性 hibernate.dialect:一个Hibernat ...
随机推荐
- 远程连接SuSE系统的配置方法
今天,在VMware上搭建了SuSE Linux系统,使用xshell远程进行连接,一直连接不上,后来百度了一下,连接成功,这里总结一下配置的办法: (1):关闭防火墙 (2):配置sshd( Pas ...
- 16、NumPy ——字节交换
NumPy 字节交换 在几乎所有的机器上,多字节对象都被存储为连续的字节序列.字节顺序,是跨越多字节的程序对象的存储规则. 大端模式:指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地 ...
- display:table的几个用法
DIV+CSS的布局已经让表格布局几乎很少用到,除非表格语义性很强的情况. display:table解决了一部分需要使用表格特性但又不需要表格语义的情况, 尤其是DIV+CSS很不方便解决的问题,比 ...
- Leetcode Lect3 时间复杂度/空间复杂度
时间复杂度 复杂度 可能对应的算法 备注 O(1) 位运算 常数级复杂度,一般面试中不会有 O(logn) 二分法,倍增法,快速幂算法,辗转相除法 O(n) 枚举法,双指针算法,单调栈算法,KMP ...
- C# Winform 窗体界面”假死”后台线程阻塞 解决办法–BeginInvoke
原文:C# Winform 窗体界面"假死"后台线程阻塞 解决办法–BeginInvoke 这个方法可以用在任何后台任务耗时较长,造成界面“假死”界面控件不更新的情况. 比如要要执 ...
- tornado后台小框架
import tornado.ioloop import tornado.web """使用get方法提交过来数据就是用get方法,使用post执行post方法这个框架的 ...
- UIViewController push或presentViewController 弹出方式
//导航控制器数量 add xjz 判断是push还是present出来的 NSArray *viewcontrollers = self.navigationController.viewContr ...
- Hibernate与 MyBatis的区别
第一章 Hibernate与MyBatis Hibernate 是当前最流行的O/R mapping框架,它出身于sf.net,现在已经成为Jboss的一部分. Mybatis 是另外一种优秀 ...
- 【LeetCode+51nod】股票低买高卖N题
[121]Best Time to Buy and Sell Stock (2018年11月25日重新复习) 给一个数组代表股票每天的价格,只能有一次交易,即一次买入一次卖出,求最大收益. 题解:用一 ...
- Jmeter --Json Extractor (后置处理器)
一.使用场景 Json Extractor 后置处理器用在返回格式为json的HTTP请求中, 用来获取返回的json中的某个值.并保存成变量供后面的请求进行调用或者断言等. 二.使用方法 1.创建H ...