objc4 流言终结者
源码都是基于objc-782,818版本,Swift5 ;老版本可能有不同的地方
[[NSObject alloc] init] 和 [NSObject new] 的区别
我采用3种方式来验证
id a = [ClassA alloc];
id aa = [[ClassA alloc] init];
id aaa = [ClassA new];
第一个,执行的堆栈,发现执行了2次 callAlloc,最终执行到_objc_rootAllocWithZone
id a = [ClassA alloc];
#0 _objc_rootAllocWithZone
#1 callAlloc(objc_class*, bool, bool)
#2 _objc_rootAlloc
#3 +[NSObject alloc]
#4 callAlloc(objc_class*, bool, bool)
#5 objc_alloc
第二个,执行堆栈,这里就有点奇怪了,感觉编译器做了优化,如果 alloc 后面紧跟 init,那么直接就执行objc_alloc_init
#0 _objc_rootAllocWithZone
#1 callAlloc(objc_class*, bool, bool)
#2 objc_alloc_init
第三个,执行堆栈,除了入口函数不一样,其他一模一样。
#0 _objc_rootAllocWithZone
#1 callAlloc(objc_class*, bool, bool)
#2 objc_opt_new
总结:
- [alloc] init ] 和 new ,执行的结果是一样的 , 面试的时候可以理直气壮的说两者是“一模一样的”。
- id a = [ClassA alloc]; [a init]; 和 id aa = [[ClassA alloc] init]; 结果是一样的,但是堆栈有较大不同
[[NSObject alloc] init] 中 init 是做初始化的工作么?
id
_objc_rootInit(id obj)
{
// In practice, it will be hard to rely on this function.
// Many classes do not properly chain -init calls.
return obj;
}
总结:init 没有做任何事情
弱引用指针存储是用什么数据结构?
摘取了部分源码:
static weak_entry_t *
weak_entry_for_referent(weak_table_t *weak_table, objc_object *referent)
{
ASSERT(referent);
weak_entry_t *weak_entries = weak_table->weak_entries;
if (!weak_entries) return nil;
size_t begin = hash_pointer(referent) & weak_table->mask;
size_t index = begin;
size_t hash_displacement = 0;
while (weak_table->weak_entries[index].referent != referent) {
index = (index+1) & weak_table->mask;
if (index == begin) bad_weak_table(weak_table->weak_entries);
hash_displacement++;
if (hash_displacement > weak_table->max_hash_displacement) {
return nil;
}
}
return &weak_table->weak_entries[index];
}
答案:存储的方式是数组,但是用了Hash算法-开放定位法,所以存储的是Hash表
分类重写主类的方法,会把函数替换掉么?
答:不会,函数替换只是表面现象;主要原因是函数寻找过程,优先寻找到分类的方法,主函数的方法其实还是存在的。
ClassA +load 中执行 [ClassB alloc],在ClassB +load 执行 [ClassA alloc] 会怎么样
// Call +load methods (without runtimeLock - re-entrant)
call_load_methods();
答:不会存在任何问题,1:load方法执行的时候,类的相关信息都已经准备完毕 2:执行load方法,没有添加 runtime lock,所以不会出现死锁现象
UIView设置Frame,是直接设置CALayer的Frame么,为什么CALayer有隐式动画而UIView没有
答:大部分设置UIView的属性,都会设置到CALayer上,而没有出现动画是因为CAAction,只有在UIView.animation block里面,uiview作为calayer的代理才会返回CAAction , 参考官方文档
NSNumber *number1 = @(1); 和 NSNumber *number2 = @(0xEFFFFFFFFFFFFFFF); 有什么区别
总结:TaggedPointer的区别,理论上TaggedPointer可以存储7个字节+ 4bit = 60bit的大小数据
ARC下 什么情况下会执行对象的autoRelease方法
//todo
Swift中函数调用用什么方式
答:静态派发和动态派发,动态派发又分 虚拟表派发 和 消息发送(@objc)
Swift中结构体或者基础数据中,函数是调用是什么方式
答:静态派发
Swift中扩展的函数,是什么调用方式
答:静态派发
Swift中结构体中使用Block,会出现循环引用的情况么?
//todo
Swift中数组范型可以用协议么?为什么
答:可以,如果数组范型是协议,那么数组存储的是一个特殊的数据结构,witnessTable,具体参考文档