1、@property 后面可以有哪些修饰符?
1.读写性修饰符:readwrite | readonly
readwrite:表明这个属性是可读可写的,系统为我们创建这个属性的setter和getter方法。
readonly:表明这个属性只能读不能写,系统只为我们创建一个getter方法,不会创建setter方法
2.setter相关修饰符:assign | retain | copy
setter相关的修饰符表明setter方法应该如何实现
assign:表示直接赋值,用于基本数据类型(NSInteger和CGFloat)和C数据类型(如int, float, double, char等)另外还有id类型,这个修饰符不会牵涉到内存管理。但是如果是对象类型,使用此修饰符则可能会导致内存泄漏或EXC_BAD_ACCESS错误
retain:针对对象类型进行内存管理。如果对基本数据类型使用,则Xcode会直接报错。当给对象类型使用此修饰符时,setter方法会先将旧的对象属性release掉,再对新的对象进行一次赋值并进行一次retain操作
copy:主要用在NSString类型,表示复制内容。
系统默认属性是assign。retain是指针的复制,copy是内容的复制
3.原子性修饰符:atomic | nonatomic
atomic:表示是线程安全的。
nonatomic:表示是非线程安全的,使用此属性性能会提高一些。
系统默认是atomic
4.getter和setter修饰符
@property(getter = getMethodName, setter = setMethodName) Object *obj;
这两个属性修饰符用于设置自定义生成的getter和setter方法名,使用之后将不再使用系统默认的setter和getter方法名。
在@property修饰符中可以出现多个修饰符,分别用逗号分隔,但是,在上述修饰符中,1,2,3组中的属性分别之恩那个出现一个,只有4中可以同时出现。
Xcode4.2(iOS sdk4.3和以下版本)和以前的版本用retain和assign
Xcode4.3(iOS 5和以上版本)或之后有了ARC用strong和weak
assign:用于非指针变量。用于基础数据类型(如NSInteger, CGFloat)和C数据类型(int, float, double, char等), 另外还有id类型。
记住:前面不需要加*的就用assign
retain:用于指针变量。一般用于字符串(NSString, NSMutableString), 数组(NSMutableArray, NSArray),字典对象,视图对象(UIView),控制器对象(UIViewController)等
strong类似于retain,weak类似于assign
最简单的记忆:
使用assign:对基础数据类型(如NSInteger, CGFloat)和C数据类型(int, float, double, char等), 另外还有id类型
使用copy:对NSString类型
使用retain:对其它NSObject和其子类
1、在头文件中用@property声明一个属性名,编译器会自动为我们转换成这个属性名的getter方法和setter方法。
2、在实现文件中使用@synthesize propertyName,编译器先会查找这个属性名的setter方法和getter方法有没有被人为实现,如果已经实现,则不再实现,如果没有,则会帮我们生成一个属性命的setter方法和getter方法。
3、当在实现文件中使用了@synthesize propertyName,编译器还会做一件事情,在类成员变量中查找一个名为_propertyName的成员变量,如果没有,再继续查找名为propertyName的成员变量,如果这两个都没有,编译器会自动为我们生成一个私有的名为_propertyName的成员变量。注意,系统自动创建的都是私有的。
4、当在实现文件中这样写@synthesize propertyName = varName;时,setter和getter方法所对应的是一个名为varName的成员变量,修改和读取的是varName成员变量的值。
5、当我们在实现文件中不写@synthesize propertyName时,在Xcode 4.5之前的版本不会帮我们自动实现setter和getter方法,系统当然也不再会为我们生成对应的成员变量。但是在Xcode 4.5之后可以不用写@synthesize了,就跟3、4一样了。
6、当我们既定义了@synthesize,又在实现文件中人为重写setter和getter方法时,那么@synthesize将不再工作,也就不会为我们创建没有定义的_propertyName成员变量了,这时候如果在setter和getter方法中调用_propertyName将会发生编译错误!
2、什么情况使用 weak 关键字,相比 assign 有什么不同?
assign是指针赋值,不对引用计数操作,使用之后如果没有置为nil,可能就会产生野指针;而weak一旦不进行使用后,永远不会使用了,就不会产生野指针!
在 ARC 中,在有可能出现循环引用的时候,往往要通过让其中一端使用 weak 来解决,比如: delegate 代理属性
自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用 weak,自定义 IBOutlet 控件属性一般也使用 weak;当然,也可以使用strong。在下文也有论述:
不同点:
weak 此特质表明该属性定义了一种“非拥有关系” (nonowning relationship)。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特质同assign类似,然而在属性所指的对象遭到摧毁时,属性值也会清空(nil out)。而 assign 的“设置方法”只会执行针对“纯量类型” (scalar type,例如 CGFloat 或 NSlnteger 等)的简单赋值操作。
assigin 可以用非 OC 对象,而 weak 必须用于 OC 对象
3、iOS开发怎么使用copy关键字
使用场景;
(1)、NSString、NSArray、NSDictionary等经常使用copy关键字
原因:因为父类指针可以指向子类对象,使用copy的目的是为了让本对象的属性不受外界影响,使用copy无论给我传入是一个可变对象还是不可对象, 我本身持有的就是一个不可变的副本.,如果我们使用是strong,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那 么会影响该属性.
//User.h文件中
@property (nonatomic, strong)NSString *name;此时若将一个可变字符串set给name,那么此时的name则指向的是一个可变字符
那么就无法保证name的不可变性
@property (nonatomic, copy)NSString *name;此时若将一个可变字符串set给name,此时会执行[MutableString copy]内容复 制,即深复制,将返回一个不可变字符串,即name指向的是一个不可变字符串,以后即使MutableString改变也不会影响name的值
例如:
NSMutableString *string = [NSMutableString stringWithString:@"origin"];//copy
NSString *stringCopy = [string copy];
[string appendString:@"origion!"]
此时的打印结果:string:originorigion!,而stringCopy仍为:origin
(2)、block也经常使用copy关键字
原因:block使用copy是从MRC遗留下来的“传统”,在MRC中,方法内部的block是在栈区的,使用copy可以把它放到堆区.在ARC中写不写都行:对于
block使用copy还是strong效果是一样的,但写上copy也无伤大雅,还能时刻提醒我们:编译器自动对block进行了copy操作
需要注意:
NSMutableString、NSMutableArray、NSMutableDictionary,使用copy应注意
原因:1、添加,删除,修改数组内的元素的时候,程序会因为找不到对应的方法而崩溃.因为copy就是复制一个不可变NSArray的对象;
2、使用了atomic属性会严重影响性能。
在非集合类对象中:对immutable对象进行copy操作,是指针复制,mutableCopy操作时内容复制;对mutable对象进行copy和mutableCopy都是 内容复制。用代码简单表示如下:
[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //深复制
[mutableObject copy] //深复制
[mutableObject mutableCopy] //深复制