@property中有哪些属性关键字?
@property和@synthesize是成对出现的,可以自动生成某个类成员变量的存取方法(getter和setter)。在Xcode4.5以及以后的版本中,@synthesize可以省略。
atomic与nonatomic
atomic:默认是有该属性的,这个属性是为了保证程序在多线程情况下,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步的问题,提供多线程安全。
nonatomic:如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,禁止多线程,变量保护,提高性能和效率。
注:
atomic是Objc使用的一种线程保护技术,基本上来讲是防止在写未完成的时候另一个线程读取,造成的数据错误。而这种机制是非常耗费系统资源的,所以iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。而iOS开发中,普遍使用nonatomic也是基于性能这一点。readwrite与readonly
readwrite:这个属性是默认的情况,会自动为你生成存取器。
readonly:只生成getter,不会生成setter方法。
注:
readwrite、readonly这两个属性的真正价值,不是提供成员变量的访问接口,而是控制成员变量的访问权限。strong与weak
strong:强引用,也是我们通常说的引用,其存亡直接决定了所指向对象的存亡,当强引用指向了某个对象,那便拥有了这个对象。如果不存在指向一个对象的引用,并且此对象不再使用,则对象就会被从内存中释放掉。默认所有实例变量和局部变量都是strong指针。
weak:弱引用,不决定对象的存亡,只是单纯的引用了某个对象但是并不拥有该对象。即使一个对象被持有无数个弱引用,只要没有强引用指向它,那么还是会被清除。
注:
strong与retain功能相似;weak与assign相似,只是当对象消失后weak会自动把指针置为nil,避免了野指针的产生,因而weak属性就不需要在dealloc中置nil了。assign、copy、retain
assgin:默认类型,setter方法直接赋值,不进行任何的retain操作,不改变引用计数。一般用来处理基本数据类型。
retain:释放旧的对象(release),将旧对象的值赋给新对象,再令新对象引用计数为1。可理解为指针拷贝。
copy:与retain的流程一样,先对旧的值release,再copy出新的对象,引用计数为1,为了减少对上下文的依赖而引入的机制。可以理解为内容的拷贝,也就意味着内容被copy后,内存中会有两个存储空间存储同样的内容。
注:
使用assign: 对基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等)
使用copy: 对NSString
使用retain: 对其他NSObject和其子类
@synthesize和@dynamic分别有什么作用?
简单来讲,通过@synthesize指令告诉编译器在编译期间产生getter和setter方法。如果自定义getter和setter方法则会覆盖编译器帮我们生成的方法。
@dynamic指令告诉编译器在编译期间不自动生成getter和setter方法,避免编译期间产生警告。然后由自己实现存取方法或存取方法在运行时动态创建绑定。其主要作用就是用在NSManageObject对象的属性声明中,由于此类对象的属性一般是从Core Data的属性中生成的,Core Data框架会在程序运行的时候为此类属性生成getter和setter方法。
ARC下,不显式指定任何属性关键字时,默认的关键字都有哪些?
atomic,readwrite,strong(对象),assgin(基本数据类型)。
用@property声明的NSString、NSArray、NSDictionary经常使用copy关键字,为什么?如果改用strong关键字,可能造成什么问题?
这个问题无非就是考察你对copy、strong这个两个修饰符的理解。简单来讲,strong是强引用,仍旧指向同一个内存地址;copy是内容拷贝,会另外开辟一个内存空间来存储被拷贝的内容,指针指向了一个不同的内存地址。注意,copy返回的是一个不可变对象。如果用strong修饰可变对象,那么这个对象就会有可能在不经意间被修改,有时候这并不是我们的想要看到的,而用copy便不会有这种意外发生了。
@synthesize合成实例变量的规则是什么?假如property名为foo,存在一个名为_foo的实例变量,那么还会自动合成新变量么?
@synthesize表示由编译器来自动实现属性的getter/setter方法,不需要你自己再手动去实现。默认情况下,不需要指定实例变量的名称,编译器会自动生成一个属性名前加“_”的实例变量。当然也可以在实现代码里通过@synthesize语法来指定实例变量的名字。比如@synthesize foo = oof
(oof为你想要定义的名称)。
如果property名为foo并且存在一个名为_foo的实例变量,编译器便不会为我们自动合成新变量了。下面有一段代码大家可以试一下帮助更好的理解。
@interface ViewController : UIViewController
@property (copy, nonatomic) NSString *testA;
@property (copy, nonatomic) NSString *testB;
@end
@interface ViewController ()
{
NSString *_testA;
NSString *_testB;
}
@end
@implementation ViewController
@synthesize testB = testBBBBB;
- (void)viewDidLoad {
[super viewDidLoad];
self.testA = @"1111";
self.testB = @"1111";
//输出结果为:self.testA = 1111,_testA = 1111,self.testB = 1111,testBBBBB = 1111,_testB = (null)
NSLog(@"self.testA = %@,_testA = %@,self.testB = %@,testBBBBB = %@,_testB = %@",self.testA,_testA,self.testB,testBBBBB,_testB);
_testA = @"2222222";
_testB = @"2222222";
//输出结果为:self.testA = 2222222,_testA = 2222222,self.testB = 1111,_testB = 2222222,testBBBBB = 1111
NSLog(@"self.testA = %@,_testA = %@,self.testB = %@,_testB = %@,testBBBBB = %@",self.testA,_testA,self.testB,_testB,testBBBBB);
testBBBBB = @"333333";
//输出结果:self.testB = 333333,testBBBBB = 333333,_testB =2222222
NSLog(@"self.testB = %@,testBBBBB = %@,_testB =%@",self.testB,testBBBBB,_testB);
}
可加群一起交流共同学习:801216530。