1.weak 和 assign 不同
1.weak 和 assign 不同
weak必须用于oc对象assign可以用于非oc对象weak可以用来解决循环引用问题weak修饰的属性表示一种非持有关系 给该对象设置新值时 设置方法既不保留新值也不释放旧值 在属性遭到摧毁时会自动制空weak可以用来修饰已经被强引用过得对象 比如使用xib进行布局时设置的属性
2.weak 的实现原理
runtime维护了一个全局的weak引用表weak_table_t(封装版本为SideTable) 其底层是一个hash表(一种key value存储的数据结构 在cpp中体现为struct) 用于存储weak引用对象key是所指对象地址value是weak指针地址weak对象释放自动置空实现: 在对象释放的最后一步objc_clear_deallocating根据对象地址获取所有weak指针的数组 遍历这个数组把其中的额数据置为空oc对象释放的顺序:objc_release,dealloc大部分对象是在这一环节被销毁的 其中主要做的事情为 object_dispose() associate 绑定的对象也是在这里销毁 所以不管是MRC还是ARC都不需要在dealloc中再次释放 associate 绑定对象,_objc_rootDealloc,objc_destructInstance,objc_clear_deallocating
3.copy修饰的属性
copy即对象的浅拷贝copy修饰的属性的值会有被保护的作用 一般copy会用来修饰不可变对象 比如NSString, NSArray等 这样的对象在被可变对象接收以后 其值仍然不可变 可以利用此封装性质封装一些数据- 自己的属性想实现
copy需要实现NSCopying协议 并实现- (id)copyWithZone:(NSZone *)zone方法
4.@property的本质
- 属性的本质是
getter+setter+ivar- 属性自动合成(autosynthesis)的规则: 自动合成会生成下面五个东西
// 该属性的偏移量 这个偏移量是硬编码 标示该变量距离存放对象的内存地址有多远 OBJC_IVAR_$类名$属性名 getter与setter方法对应的实现函数 // 成员列表 ivar_list // 方法列表 method_list // 属性列表 prop_list每增加一个属性 系统都会在
ivar_list中添加一个成员变量的描述 在method_list中增加getter与setter方法的描述 在prop_list中给出属性描述 然后计算属性在对象中的偏移量然后根据偏移量的位置 实现具体的setter方法与getter方法
5. @synthesize 和 @dynamic
@sythesize如果没有手动实现getter和setter由编译器自动创建 默认为@syntheszie var = _var;@dynamicgetter和setter都需要手动创建
6.ARC下 不指定属性任何的关键字 默认的修饰符有哪些
atomicreadwritestringoc 对象atomicreadwriteassign基本类型
7.objc_msgSend()
Objective-C是动态语言 每个方法会在运行时被动态转为消息发送 即objc_msgSend(receiver, selector)oc类的基本结构:
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY; //isa指针指向Meta Class,因为Objc的类的本身也是一个Object,为了处理这个关系,runtime就创造了Meta Class,当给类发送[NSObject alloc]这样消息时,实际上是把这个消息发给了Class Object
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE; // 父类
const char *name OBJC2_UNAVAILABLE; // 类名
long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0
long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识
long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表
struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表
struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存,对象接到一个消息会根据isa指针查找消息对象,这时会在method Lists中遍历,如果cache了,常用的方法调用时就能够提高调用的效率。
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表
#endif
} OBJC2_UNAVAILABLE;
unrecognized selector就是由于消息转发的时候没有在方法列表中找到产生的
消息转发过程
objc_msgForward:
- objc在向一个对象发送消息时
runtime会根据对象的isa指针找到该对象所属的类 然后在该类的方法列表中查找目标方法 如果该类中没有这个方法 则去父类中查找 一直查找到父类的最上层- 如果父类的最上层也没有找到相对应的方法 则会报
unrecognized selector但在这之前 仍有三次补救的机会- 第一次补救机会
Method resolution:runtime会调用本类中+resolveInstanceMethod:或+resolveClassMethod:让你提供一个函数实现 如果你添加了目标函数 那runtime会重新启动一次消息发送的过程 否则则运行到下一步 消息转发- 第二次补救机会
Fast forwarding: 如果目标对象实现了-forwardingTargetForSelector:runtime就会调用这个方法 根据这个方法返回的对象(不为nil或self)重启消息发送, 当然新的消息放松过程也会转移到返回的对象上面 否则则进行最后一次消息转发- 第三次补救机会
Normal forwarding: 首先runtime会发送-methodSignatureForSelector:获得函数的参数及返回类型 如果-methodSignatureForSelector:返回了nil这时程序就会崩溃 如果返回了一个函数签名 则runtime会生成一个NSInvocation对象并发送-forwardInvocation:给目标对象 (有些框架 例如JSPatch需要利用第三步返回的NSInvocation自定义实现 而直接调用了objc_msgForward这样原来的方法就不会被执行 而是走了别的实现)
8.下面的代码输出什么
@implementation Son : Father
- (id)init
{
self = [super init];
if (self) {
NSLog(@"%@", NSStringFromClass([self class])); // Son
NSLog(@"%@", NSStringFromClass([super class])); // Son
}
return self;
}
@end
都是
Sonsuper和self指向同一个消息接收者super会在父类中调用而已 但他仍然是本类对象
9.objc 中类方法和实例方法有什么本质区别和联系
类方法:
- 类方法是属于类对象的
- 类方法只能由类对象调用
- 类方法中的self是类对象
- 类方法可以调用其他类的方法
- 类方法中不能访问成员变量
- 类方法中不能直接调用对象方法
实例方法:
- 实例方法是属于实例对象的
- 实例方法由对象实例调用
- 实例方法中的self是实例对象
- 实例方法中可以访问成员变量
- 实例方法中可以调用实例方法
- 实例方法也可以调用类方法(通过类名)
10.能否想编译后的类中添加实例变量 运行时呢?
不能向编译后的类中添加实例变量 运行时可以 因为编译后的类已经在
runtime中注册类结构体中的实例变量链表objc_Ivar_list和实例变量内存instance_size大小已确定
运行时可以添加但的在类被创建但还没有向
runtime注册之前objc_allocateClassPair-objc_registerClassPair区间内