以下笔记内容仅供个人参考,如有理解错误,请高抬贵手,仙人指路,互相学习进步...
大纲:
1、@property是什么?
2、@property常见写法
3、手动创建存储器(繁琐)
4、使用@Property自动创建存取器(快捷)
5、@property指示符
6、深拷贝与浅拷贝、copy、mutableCopy
7、知识点总结:
8、参考链接
1、@property是什么?
理解1
@property = ivar + getter + setter;就是通过设置property属性,编译器给我们创建了一个ivar对象,并且实现了一个get方法,和一个set方法。并且我们可以通过点语法进行获取或设置属性的值.
理解2
@Property是声明属性的语法,它可以快速方便的为实例变量创建存取器,并允许我们通过点语法使用存取器。//注:存取器(accessor):指用于获取和设置实例变量的方法。用于获取实例变量值的存取器是getter,用于设置实例变量值的存取器是setter
2、@property常见写法
@property (nonatomic, strong) NSMutableString * mutableString;
@property (nonatomic, copy) NSString* name;
@property (nonatomic, assign) NSUInteger age;
@property (nonatomic, weak, nullable) id <UITableViewDelegate> delegate;
@property (nonatomic,strong, nonnull) NSMutableArray *mutableArray;
@property (nonatomic, readonly) UITableViewStyle style;
@property (nonatomic, readwrite) UITableViewStyle style;
@property (nonatomic, readwrite,setter=setMyStyle,getter=getMyStyle) NSString* style;
3、手动创建存储器(繁琐)
// Car.h
@interface Car : NSObject{
// 实例变量
NSString *carName;
NSString *carType;
}
// setter
- (void)setCarName:(NSString *)newCarName;
// getter
- (NSString *)carName;
// setter
- (void)setCarType:(NSString *)newCarType;
// getter
- (NSString *)carType;
@end
#import "Car.h"
@implementation Car
// setter
- (void)setCarName:(NSString *)newCarName{
carName = newCarName;
}
// getter
- (NSString *)carName{
return carName;
}
// setter
- (void)setCarType:(NSString *)newCarType{
carType = newCarType;
}
// getter
- (NSString *)carType{
return carType;
}
@end
使用方式
#import "Car.h"
int main(int argc, char * argv[])
{
@autoreleasepool {
Car *car = [[Car alloc] init];
[car setCarName:@"Jeep Cherokee"];
[car setCarType:@"SUV"];
NSLog(@"The car name is %@ and the type is %@",[car carName],[car carType]);
}
return 0;
}
小结:上面代码中创建了两个实例变量carName,carType,通过自定义set,get方法进行存取操作。过程太过繁琐了
4、使用@Property自动创建存取器(快捷)
@interface Car : NSObject
@property(nonatomic,copy) NSString *carName;
@property(nonatomic,copy) NSString *carType;
@end
// Car.m
#import "Car.h"
@implementation Car
//编译器会帮我们自动生成_carName和_carType这两个实例变量,.m文件中的其他代码就可以正常使用这两个变量了
//注意:系统是默认隐藏的,我们看不见,假如需要替换如@synthesize carName = myCarName;
@synthesize carName = _carName;
@synthesize carType = _carType;
@end
使用方式
点语法(推荐)
Car *car = [[Car alloc] init];
car.carName = @"Jeep Compass";
car.carType = @"SUV";
NSLog(@"The car name is %@ and the type is %@",car.carName,car.carType);
或者(自行调用)
[car setCarName:@"Jeep Cherokee"];
[car setCarType:@"SUV"];
NSLog(@"The car name is %@ and the type is %@",[car carName],[car carType]);
小结:上面代码中使用@property创建了两个实例变量carName,carType,编译器自动生成set,get方法。过程快速便捷,同时,我们可以使用点语法进行存取变量。
5、@property指示符
在声明属性的时候一般会带上几个指示符,常用指示符有
atomic nonatomic
readwrite readonly
strong
copy
assign
weak
retain
还可以设置getter和setter对其重命名
atomic、nonatomic原子、非原子
指定合成存取方法是否为原子操作,可以理解为是否线程安全,但在iOS上即时使用atomic也不一定是线程安全的,要保证线程安全需要使用锁机制,超过本文的讲解范围,可以自行查阅。
可以发现几乎所有代码的属性设置都会使用nonatomic,这样能够提高访问性能,在iOS中使用锁机制的开销较大,会损耗性能。
readwrite、readonly 可读、只读
readwrite是编译器的默认选项,表示自动生成getter和setter,如果需要getter和setter不写即可。
readonly表示只合成getter而不合成setter。
strong、copy、assign、weak、retain
strong修饰表示属性对所赋的值持有强引用表示一种“拥有关系”(owning relationship),会先保留新值即增加新值的引用计数,然后再释放旧值即减少旧值的引用计数。只能修饰对象。如果对一些对象需要保持强引用则使用strong。
copy修饰 修饰的属性会在内存里拷贝一份对象,两个指针指向不同的内存地址。
修饰不可变类型子类的对象,用copy
如:NSString,NSArray,NSDictionary等。
当修饰可变类型的属性时,用strong,如NSMutableArray、NSMutableDictionary、NSMutableString。对于可变对象类型,如NSMutableString、NSMutableArray等则不可以使用copy修饰,因为Foundation框架提供的这些类都实现了NSCopying协议,使用copy方法返回的都是不可变对象,如果使用copy修饰符在对可变对象赋值时则会获取一个不可变对象,接下来如果对这个对象进行可变对象的操作则会产生异常,因为OC没有提供mutableCopy修饰符,对于可变对象使用strong修饰符即可。具体栗子如下:
//使用copy修饰NSMutableString
@property (nonatomic, copy) NSMutableString* name;
//copy修饰会返回不可变类型。
p.name = [[NSMutableString alloc] initWithString:@"Jiaming Chen"];
//修改p.name,此时抛出异常
[p.name appendString:@" is a good guy."];
上面的栗子使用copy修饰可变对象,在进行赋值的时候会通过copy方法获取一个不可变对象,因此p.name的地址和s的地址不同,而p.name运行时类型为NSString,调用appendString:方法会抛出异常。
weak修饰表示对所赋的值对象持有弱引用表示一种“非拥有关系”(nonowning relationship),对新值不会增加引用计数,也不会减少旧值的引用计数。所赋的值在引用计数为0被销毁后,weak修饰的属性会被自动置为nil能够有效防止野指针错误。
weak常用在修饰delegate等防止循环引用的场景
assign修饰表示对属性只进行简单的赋值操作,不更改所赋的新值的引用计数,也不改变旧值的引用计数,常用于标量类型,如NSInteger,NSUInteger,CGFloat,NSTimeInterval等
注:assign也可以修饰对象如NSString等类型对象,上面说过使用assign修饰不会更改所赋的新值的引用计数,也不改变旧值的引用计数,如果当所赋的新值引用计数为0对象被销毁时属性并不知道,编译器不会将该属性置为nil,指针仍旧指向之前被销毁的内存,这时访问该属性会产生野指针错误并崩溃,
因此使用assign修饰的类型一定要为标量类型。
unsafe_unretained修饰使用unsafe_unretained修饰时效果与assign相同,不会增加新值的引用计数,也不会减少旧值的引用计数(unretained)当所赋的值被销毁时不会被置为nil可能会发生野指针错误(unsafe)。
unsafe_unretained与assign的区别在于,unsafe_unretained只能修饰对象,不能修饰标量类型,而assign两者均可修饰。
retain修饰在ARC环境下使用较少,在MRC下使用效果与strong一致。
copy,mutableCopy方法
有时候我们需要copy一个对象,或是mutableCopy一个对象,这时需要遵守NSCopying和NSMutableCopying协议,来实现copyWithZone:和mutableCopyWithZone:两个方法,而不是重写copy和mutableCopy两个方法。
Foundation框架中的很多数据类型已经帮我们实现了上述两个方法,因此我们可以使用copy方法和mutableCopy方法来复制一个对象,两者的区别在于copy的返回值仍未不可变对象,mutableCopy的返回值为可变对象
6、深拷贝与浅拷贝方法
iOS 浅谈:深.浅拷贝与copy.strong http://www.jianshu.com/p/e6a7cdcc705d
NSString不可变对象的深浅拷贝
copy浅拷贝只拷贝指针,不拷贝内容,没有创建新的对象
mutableCopy深拷贝会创建新对象,把内容也拷贝了一份,创建新的对象NSMutableString可变对象的深浅拷贝
copy、mutableCopy都属于深拷贝
7、知识点总结:
@property等同于在.h文件中声明实例变量的get/set方法
@synthesize等同于在.m文件中实现实例变量的get/set方法。(但隐藏了)
使用@property和synthesize创建存取器要比手动声明两个存取方法(getter和setter)更简单。而且我们在使用属性时可以使用点语法赋值或取值,语法更简单,更符合面向对象编程。
什么时候使用strong,copy,assign,weak?
strong常使用在可变类型:NSMutableArray、NSMutableDictionary、NSMutableString
copy常使用在不可以变类型:NSArray、NSDictionary、NSString
assign常使用在基本类型:NSInteger,NSUInteger,CGFloat,NSTimeInterval
weak常使用在delegate等防止循环引用的场景
copy方法和mutableCopy方法来复制一个对象,两者的区别在于copy的返回值仍未不可变对象,mutableCopy的返回值为可变对象
NSString不可变对象的深浅拷贝
copy浅拷贝只拷贝指针,不拷贝内容,没有创建新的对象
mutableCopy深拷贝会创建新对象,把内容也拷贝了一份,创建新的对象NSMutableString可变对象的深浅拷贝
copy、mutableCopy都属于深拷贝
NSString到底使用copy还是strong修饰呢?为什么呢?
应该使用copy修饰,使用copy是为了保证属性值的安全,不被其他变量的变化影响。
如下代码所示:
//假如使用strong来修饰NSString
@property (nonatomic, strong) NSString *name;
NSMutableString*mutableStr= [[NSMutableString alloc] initWithString:@"黎"];
p.name = mutableStr;
NSLog(@"%@",p.name); //会输出“黎”
[mutableStr appendString:@"明"];
NSLog(@"%@",p.name); //会输出“黎明”
8、参考链接
http://www.cocoachina.com/ios/20150123/11003.html
http://blog.csdn.net/u014205968/article/details/64443443
很好的一个博文:iOS 浅谈:深.浅拷贝与copy.strong http://www.jianshu.com/p/e6a7cdcc705d
@property进阶 http://blog.csdn.net/u014205968/article/details/64443487