关于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 详解的更多相关文章

  1. log4j.properties 详解与配置步骤(转)

    找的文章,供参考使用 转自 log4j.properties 详解与配置步骤 一.log4j.properties 的使用详解 1.输出级别的种类 ERROR.WARN.INFO.DEBUGERROR ...

  2. SpringBoot配置文件 application.properties详解

    SpringBoot配置文件 application.properties详解   本文转载:https://www.cnblogs.com/louby/p/8565027.html 阅读过程中若发现 ...

  3. log4j.properties 详解与配置步骤

    一.log4j.properties 的使用详解 1.输出级别的种类 ERROR.WARN.INFO.DEBUGERROR 为严重错误 主要是程序的错误WARN 为一般警告,比如session丢失IN ...

  4. [转]application.properties详解 --springBoot配置文件

    本文转载:http://blog.csdn.net/lpfsuperman/article/details/78287265###; # spring boot application.propert ...

  5. application.properties详解 --springBoot配置文件【转载】

    # spring boot application.properties配置的各个属性详解 # 该示例文件作为标准提供.(官方文档 翻译过来的) # 还是花了些功夫翻译,各位如果转发,请留下本文地址, ...

  6. application.properties详解 --springBoot配置文件

    本文转载:http://blog.csdn.net/lpfsuperman/article/details/78287265###; # spring boot application.propert ...

  7. 转--log4j.properties 详解与配置步骤

    一.log4j.properties 的使用详解 1.输出级别的种类 ERROR.WARN.INFO.DEBUGERROR 为严重错误 主要是程序的错误WARN 为一般警告,比如session丢失IN ...

  8. log4j.properties 详解与配置步骤总结

    先提供一个项目中使用log4j.properties配置 #log4j.rootLogger=WARN, stdout, file log4j.rootLogger=INFO,console,dail ...

  9. 【转】log4j.properties 详解与配置步骤 - edward0830ly的专栏 - 博客频道 - CSDN.NET

    一.log4j.properties 的使用详解 1.输出级别的种类 ERROR.WARN.INFO.DEBUGERROR 为严重错误 主要是程序的错误WARN 为一般警告,比如session丢失IN ...

  10. (转)spring hibernate properties详解

    转载地址:http://blog.sina.com.cn/s/blog_692d0a650100xyqx.html Hibernate配置属性 hibernate.dialect:一个Hibernat ...

随机推荐

  1. 702:Crossing River (贪心)

    [题目描述] N个人过河,一次过去2个回来一个,给出每个人所需时间,问最小过河时间. [题目链接] http://noi.openjudge.cn/ch0406/702/ [算法] 一开始想样例是怎么 ...

  2. An easy problem (位运算)

    [题目描述] 给出一个整数,输出比其大的第一个数,要求输出的数二进制表示和原数二进制表示下1的个数相同. [题目链接] http://noi.openjudge.cn/ch0406/1455/ [算法 ...

  3. Codeforces Round #574 (Div. 2) A~E Solution

    A. Drinks Choosing 有 $n$ 个人,每个人各有一种最喜欢的饮料,但是买饮料的时候只能同一种的两个两个买(两个一对) 学校只打算卖 $\left \lceil \frac{n}{2} ...

  4. Mac下安装nodejs,然后安装Vue-devtools工具

    一.安装nodejs 1.这一步简单,只要上官网下载下来,直接按照提示安装就可以,mac版本的安装方法很简单. 下载nodejs的官方网址是:  nodejs.org    ,浏览器输入就可以跳转到了 ...

  5. 数组降维-JavaScript中apply方法妙用

    海纳百川,有容乃大 1.普通循环转换方式 将多维数组(尤其是二维数组)转化为一维数组是业务开发中的常用逻辑,除了使用朴素的循环转换以外,我们还可以利用Javascript的语言特性实现更为简洁优雅的转 ...

  6. RabbitMQ ——与Spring集成及exchange的direct、topic方式实现和简单队列实现

    程序整体结构 Maven依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http: ...

  7. 【知识强化】第三章 存储系统 3.5 双口RAM和多模块存储器

    下面我们进入双端口RAM和多模块存储器的学习.这是提高我们的存储器的访存速度的一些措施. 我们之前已经讲过我们的主存和CPU是进行连接的,那么这就导致了一个问题就是说,随着我们现代科技的发展,计算机的 ...

  8. lodash throttle和debounce

    https://lodash.com/docs#debounce throttle(又称节流)和debounce(又称防抖)其实都是函数调用频率的控制器 throttle:将一个函数的调用频率限制在一 ...

  9. PoisonTap - 在锁屏电脑上窃取cookies,获得电脑路由,安装网络后门的工具

    工具地址:https://samy.pl/poisontap/ 当PoisonTap(由Raspberry Pi Zero & Node.js开发)接入到一个锁屏或者用密码保护的电脑上时,它可 ...

  10. 对于一般情况X1+X2+X3+……+Xn=m 的正整数解有 (m-1)C(n-1) 它的非负整数解有 (m+n-1)C(n-1)种

    对于一般情况X1+X2+X3+……+Xn=m 的正整数解有 (m-1)C(n-1) 它的非负整数解有 (m+n-1)C(n-1)种