12. ARC下,不显式指定任何属性关键字时,默认的关键字都有哪些?
对应基本数据类型默认关键字是
atomic,readwrite,assign
对于普通的OC对象
atomic,readwrite,strong
13. 用@property声明的NSString(或NSArray,NSDictionary)经常使用copy关键字,为什么?如果改用strong关键字,可能造成什么问题?
1)因为父类指针可以指向子类对象,使用copy的目的是为了让本对象的属性不受外界影响,使用copy无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本.
2)如果我们使用是strong,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性.
copy此特质所表达的所属关系与strong类似。然而设置方法并不保留新值,而是将其“拷贝” (copy)。 当属性类型为NSString时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个NSMutableString类的实例。这个类是NSString的子类,表示一种可修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变” (immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的” (mutable),就应该在设置新属性值时拷贝一份。
为了理解这种做法,首先要知道,对非集合类对象的copy操作:
在非集合类对象中:对immutable对象进行copy操作,是指针复制,mutableCopy操作时内容复制;对mutable对象进行copy和mutableCopy都是内容复制。用代码简单表示如下:
[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //深复制
[mutableObject copy] //深复制
[mutableObject mutableCopy] //深复制
14. @synthesize合成实例变量的规则是什么?假如property名为foo,存在一个名为_foo的实例变量,那么还会自动合成新变量么?
在回答之前先说明下一个概念:
实例变量 = 成员变量 = ivar
1)如果指定了成员变量的名称,会生成一个指定的名称的成员变量,
2)如果这个成员已经存在了就不再生成了.
3)如果是 @synthesize foo; 还会生成一个名称为foo的成员变量,也就是说:如果没有指定成员变量的名称会自动生成一个属性同名的成员变量。
4)如果是 @synthesize foo = _foo; 就不会生成成员变量了.
15. 在有了自动合成属性实例变量之后,@synthesize还有哪些使用场景?
回答这个问题前,我们要搞清楚一个问题,什么情况下不会autosynthesis(自动合成)?
同时重写了setter和getter时
重写了只读属性的getter时
使用了@dynamic时
在 @protocol 中定义的所有属性
在 category 中定义的所有属性
重载的属性
当你在子类中重载了父类中的属性,你必须 使用@synthesize来手动合成ivar。
除了后三条,对其他几个我们可以总结出一个规律:当你想手动管理@property的所有内容时,你就会尝试通过实现@property的所有“存取方法”(the accessor methods)或者使用@dynamic来达到这个目的,这时编译器就会认为你打算手动管理@property,于是编译器就禁用了autosynthesis(自动合成)。
因为有了autosynthesis(自动合成),大部分开发者已经习惯不去手动定义ivar,而是依赖于autosynthesis(自动合成),但是一旦你需要使用ivar,而autosynthesis(自动合成)又失效了,如果不去手动定义ivar,那么你就得借助@synthesize来手动合成ivar。
16. objc中向一个nil对象发送消息将会发生什么?
在Objective-C中向nil发送消息是完全有效的——只是在运行时不会有任何作用:
如果一个方法返回值是一个对象,那么发送给nil的消息将返回0(nil)。例如:
1
|
Person * motherInlaw = [[aPerson spouse] mother];
|
如果spouse对象为nil,那么发送给nil的消息mother也将返回nil。
1)如果方法返回值为指针类型,其指针大小为小于或者等于sizeof(void*),float,double,long double 或者long long的整型标量,发送给nil的消息将返回0。
2)如果方法返回值为结构体,发送给nil的消息将返回0。结构体中各个字段的值将都是0。
3)如果方法的返回值不是上述提到的几种情况,那么发送给nil的消息的返回值将是未定义的。
具体原因如下:
objc是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。
17. objc中向一个对象发送消息[obj foo]和objc_msgSend()函数之间有什么关系?
具体原因同上题:该方法编译之后就是objc_msgSend()函数调用.如果我没有记错的大概是这样的:
1
|
((void ()(id, SEL))(void )objc_msgSend)((id)obj, sel_registerName(
"foo"
));
|
也就是说:
[obj foo];在objc动态编译时,会被转意为:objc_msgSend(obj, @selector(foo));。
18. 什么时候会报unrecognized selector的异常?
简单来说:当该对象上某个方法,而该对象上没有实现这个方法的时候, 可以通过“消息转发”进行解决。
简单的流程如下,在上一题中也提到过:objc是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。
19. 一个objc对象如何进行内存布局?(考虑有父类的情况)
所有父类的成员变量和自己的成员变量都会存放在该对象所对应的存储空间中.
每一个对象内部都有一个isa指针,指向他的类对象,类对象中存放着本对象的
1)对象方法列表(对象能够接收的消息列表,保存在它所对应的类对象中)
2)成员变量的列表
3)属性列表
20. 一个objc对象的isa的指针指向什么?有什么作用?
指向他的类对象,从而可以找到对象上的方法
21. 下面的代码输出什么?
1
2
3
4
5
6
7
8
9
10
11
|
@implementation Son : Father
- (id)init
{
self = [
super
init];
if
(self) {
NSLog(@
"%@"
, NSStringFromClass([self class]));
NSLog(@
"%@"
, NSStringFromClass([
super
class]));
}
return
self;
}
@end
|
都输出 Son
22. runtime如何通过selector找到对应的IMP地址?(分别考虑类方法和实例方法)
每一个类对象中都一个方法列表,方法列表中记录着方法的名称,方法实现,以及参数类型,其实selector本质就是方法名称,通过这个方法名称就可以在方法列表中找到对应的方法实现.
23. 使用runtime Associate方法关联的对象,需要在主对象dealloc的时候释放么?
无论在MRC下还是ARC下均不需要
24. objc中的类方法和实例方法有什么本质区别和联系?
类方法:
类方法是属于类对象的
类方法只能通过类对象调用
类方法中的self是类对象
类方法可以调用其他的类方法
类方法中不能访问成员变量
类方法中不定直接调用对象方法
实例方法:
实例方法是属于实例对象的
实例方法只能通过实例对象调用
实例方法中的self是实例对象
实例方法中可以访问成员变量
实例方法中直接调用实例方法
实例方法中也可以调用类方法(通过类名)
原文:http://my.oschina.net/rainwz/blog/511802