回头聊聊@property、copy和深浅拷贝
2017-02-26 本文已影响102人
eb2d18a460fb
聊聊@property、copy和深浅拷贝
关于property的由来
property
关键字为我们自动地生成 setter/getter 方法。
早前OC中成员变量中accessor方法(setter/getter)需要自己构建,大多数时候都是重复的代码。比如对象的成员声明要这么写:
*.h
@interface Obj : NSObject{
NSString *_name;
}
- (NSString *)name;
- (void)setName:(NSString *)name;
@end
*.m
@implementation Obj
- (NSString *)name
{
return _name;
}
- (void)setName:(NSString *)name
{
_name = name;
}
@end
使用的时候这样做:
Obj *o = [[Obj alloc] init];
[o setName:@"my name!"];
NSString *name = [o name];
NSLog(@"%@", name);
当然上面的代码仅用于展示,在使用这个写法的时候还是手动进行内存管理。
上面的情况在成员变量较多的时候非常麻烦,java IDE提供了相应的功能来为我们自动添加,但Xcode选择了另一条路,引入了@property
和@synthesize
来拯救我们,由 @property 生成.h中的声明语句,由 @synthesize 生成.m中的实现语句,代码大概是这样:
.h
@interface Obj : NSObject
@property NSString *name;
@end
.m
@implementation Obj
@synthesize name;
@end
这样清爽多了,后来苹果的工程师觉得这样写感觉还是多余了,于是决定帮再简化一点,在Xcode4.5后,只要有 @property 即可:
.h
@interface Obj : NSObject
@property NSString *name;
@end
.m
@implementation Obj
@end
配合 .
点语法,使用的时候不再通过OC独有的消息机制的写法来表达:
Obj *o = [[Obj alloc] init];
o.name = @"my name!";
NSString *name = o.name;
了解@property (nonatomic, strong, readwrite)的意义
到这里,我们知道这 @property 实际上做了哪些事情了,下面我们再来谈谈我们更关心的参数问题,举一个完整的例子:
@property (nonatomic, strong, readwrite) NSObject *obj;
property 声明的时候需要说明三个参数:
- nonatomic / atomit
- atomit 线程保护,默认
- nonatomic 非线程保护
- strong / weak / copy
- weak 弱引用,不持有对象,对应MRC时代的 assign,默认(常用于:delegate)
- strong 强引用,持有对象,对应MRC时代的 retain
- copy 复制一个新对象(常用于:NSString)
- readwrite / readonly
- readwrite 生成get和set方法,默认
- readonly 只生成get方法
copy / mutableCopy
- copy:生成一个新的不可变对象
- mutableCopy:生成一个新的可变对象
深拷贝与浅拷贝
苹果对于深拷贝与浅拷贝的说明,一目了然
核心内容看下图便明了,
![主要见图](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Collections/Art/CopyingCollections_2x.png)
在Foundation对象中,默认是浅拷贝。以数组为例,浅拷贝(Shallo copy)仅对数组进行拷贝,与原数组共用其中的 Item, 深拷贝(Deep copy)对 数组及其中的 Item 都进行完全的拷贝,就是我们正常理解的拷贝。
其它
NSString
NSString拥有自己的内存管理机制和优化,使用时一般这样声明。
@property (nonatomic, copy) NSString *str;
我现在记忆比较深刻的优化内容如下:
NSString *str1 = [[NSString alloc] init];
NSString *str2 = @"a string.";
//此时 str1 和 str2 被保存在两个不同的内存区域
str1 = str2;
//此时 str1 的地址与 str2 相同
assign/retain/copy的实现方式
// assign
-(void)setTestObject :(id)newValue{
testObject= newValue;
}
// retain
-(void)setTestObject :(id)newValue{
if (testObject!= newValue) {
[testObject release];
testObject= [newValue retain];
}
}
// copy
-(void)setTestObject :(id)newValue{
if (testObject != newValue) {
[testObject release];
testObject = [newValue copy];
}
}
版权声明:本文为本人原创文章,未经作者允许不得转载。