iOS面试ios面试知识复习

@property的本质

2016-06-30  本文已影响984人  纳木错_grace

@property的本质

@property = ivar(实例变量)+getter + setter(存取方法)

“属性” (property)作为 Objective-C 的一项特性,主要的作用就在于封装对象中的数据。 Objective-C 对象通常会把其所需要的数据保存为各种实例变量。实例变量一般通过“存取方法”(access method)来访问。其中,“获取方法” (getter)用于读取变量值,而“设置方法” (setter)用于写入变量值。这个概念已经定型,并且经由“属性”这一特性而成为 Objective-C 2.0 的一部分。 而在正规的 Objective-C 编码风格中,存取方法有着严格的命名规范。 正因为有了这种严格的命名规范,所以 Objective-C 这门语言才能根据名称自动创建出存取方法。

也可以说:@property = getter + setter;

ivar、getter、setter 是如何生成并添加到这个类中的?

完成属性定义后,编译器会自动编写访问这些属性所需的方法,此过程叫做“自动合成”(autosynthesis)。除了生成方法代码 getter、setter 之外,编译器还要自动向类中添加适当类型的实例变量,并且在属性名前面加下划线,以此作为实例变量的名字。

 @protocol 和 category 中如何使用 @property

在 protocol 中使用 property 只会生成 setter 和 getter 方法声明,我们使用属性的目的,是希望遵守我协议的对象能实现该属性

category 使用 @property 也是只会生成 setter 和 getter 方法的声明,如果我们真的需要给 category 增加属性的实现,需要借助于运行时的两个函数:

1,objc_setAssociatedObject

2,objc_getAssociatedObject

ARC下,不显式指定任何属性关键字时,默认的关键字都有哪些?

对应基本数据类型默认关键字是

atomic,readwrite,assign

对于普通的 Objective-C 对象

atomic,readwrite,strong

用@property声明的NSString(或NSArray,NSDictionary)经常使用copy关键字,为什么?如果改用strong关键字,可能造成什么问题?

重写带copy关键字的setter方法

-  (void)setName:(NSString *)name {

   _name = [name copy];

}

1,因为父类的指针可以指向子类的对象,使用copy的目的是为了让本对象的属性不受外界影响,使用copy无论给我传入一个可变对象还是不可变对象,我本身持有的就是一个不可变的副本。

2,如果我们使用时strong,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部修改了,那么会影响该属性,copy特质所表达的所属关系与strong类似,然而设置方法并不保留新值,而是将其拷贝,当属性类型是NSString时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个NSMutableString类的实例,这个类是 NSString 的子类,表示一种可修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变” (immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的” (mutable),就应该在设置新属性值时拷贝一份。

深复制和浅复制

1,对非集合类的对象的copy和mutableCopy操作。

在非集合类对象中,对不可变对象进行copy操作,是指针复制,mutableCopy操作时是内容复制。对可变对象进行copy和mutableCopy都是内容复制。

[immutableObject copy] // 浅复制

[immutableObject mutableCopy] //深复制

[mutableObject copy] //深复制

[mutableObject mutableCopy] //深复制

例如:

NSMutableString *string = [NSMutableString stringWithString:@"origin"];//copy

NSString *stringCopy = [string copy];

查看内存,会发现 string、stringCopy 内存地址都不一样,说明此时都是做内容拷贝、深拷贝。即使你进行如下操作:

[string appendString:@"origion!"]

stringCopy 的值也不会因此改变,但是如果不使用 copy,stringCopy 的值就会被改变。 集合类对象以此类推。 所以,

用 @property 声明 NSString、NSArray、NSDictionary 经常使用 copy 关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,他们之间可能进行赋值操作,为确保对象中的字符串值不会无意间变动,应该在设置新属性值时拷贝一份。

2,对集合类的对象的copy和mutableCopy操作。

集合类对象是指 NSArray、NSDictionary、NSSet ... 之类的对象。

 集合类immutable对象使用 copy 和 mutableCopy 的一个例子:

NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"]];

NSArray *copyArray = [array copy];

NSMutableArray *mCopyArray = [array mutableCopy];

查看内存,可以看到 copyArray 和 array 的地址是一样的,而 mCopyArray 和 array 的地址是不同的。说明 copy 操作进行了指针拷贝,mutableCopy 进行了内容拷贝。但需要强调的是:此处的内容拷贝,仅仅是拷贝 array 这个对象,array 集合内部的元素仍然是指针拷贝。

mutable 对象拷贝的例子:

NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];

NSArray *copyArray = [array copy];

NSMutableArray *mCopyArray = [array mutableCopy];

查看内存,copyArray、mCopyArray和 array 的内存地址都不一样,说明 copyArray、mCopyArray 都对 array 进行了内容拷贝。同样,我们可以得出结论

在集合类对象中,对 immutable 对象进行 copy,是指针复制, mutableCopy 是内容复制;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。但是:集合对象的内容复制仅限于对象本身,对象元素仍然是指针复制。 

[immutableObject copy] // 浅复制

[immutableObject mutableCopy] //单层深复制

[mutableObject copy] //单层深复制

[mutableObject mutableCopy] //单层深复制

上一篇下一篇

猜你喜欢

热点阅读