前几天看到一篇文章非科班iOS开发者的面试总结,记录了一个非科班iOS程序员面试时候的困惑,从侧面反映出当前行业的现状。
iOS行业在经历了过去几年的爆发期后,现在到了一个相对冷静的时期,一个良币驱逐劣币、去伪存真的阶段。只有持续的专注和付出,才能够在激烈的竞争中脱颖而出,成为强者。正如狄更斯所言,“这是一个最坏的时代,也是最好的时代” 。
对于这些面试题,不要死记硬背,应该举一反三,深刻理解实现机制(这也是科班和非科班的区别之一)。面试题答案只是参考,如有错误请指正。
如果让你实现属性的weak,如何实现的?
runtime
对注册的类会进行布局,对于weak
修饰的对象会放入一个hash
表中。用weak指向的对象内存地址作为key,当此对象的引用计数为0的时候会dealloc
,假如weak
指向的对象内存地址是a,那么就会以a为键在这个weak表中搜索,找到所有以a为键的weak
对象,从而设置为nil
。
如果让你来实现属性的atomic,如何实现?
- (void)setCurrentImage:(UIImage *)currentImage
{
@synchronized(self) {
if (_currentImage != currentImage) {
[_currentImage release];
_currentImage = [currentImage retain];
// do something
}
}
}
- (UIImage *)currentImage
{
@synchronized(self) {
return _currentImage;
}
}
KVO为什么要创建一个子类来实现?
Runtime动态生成一个NSKVONotifying_Class子类,可以动态地添加willChangeValueForKey
和didChangeValueForKey
观察所有属性的变化
类结构体的组成,isa指针指向了什么?(这里应该将元类和根元类也说一下)
isa:是一个Class 类型的指针. 每个实例对象有个isa的指针,他指向对象的类,而Class里也有个isa的指针, 指向meteClass(元类)。元类保存了类方法的列表。当类方法被调用时,先会从本身查找类方法的实现,如果没有,元类会向他父类查找该方法。同时注意的是:元类(meteClass)也是类,它也是对象。元类也有isa指针,它的isa指针最终指向的是一个根元类(root meteClass).根元类的isa指针指向本身,这样形成了一个封闭的内循环。
RunLoop有几种事件源?有几种模式?
Runloop(消息循环)的目的:
1. 基本作用:保持程序的持续运行,保证程序不退出
2. 处理App中的各种事件(比如触摸事件,定时器事件,Selector事件)
3. 节省CPU资源,提高程序性能:该做事时做事,该休息是休息
- 事件源:输入源和定时源
- 模式:有4种模式 第一种就是默认模式: 也就是一般的方法调用使用的模式。第二种就是跟踪模式: 用于scrollview追踪触摸滑动, 使其不受其他模式的影响, 可以共存。 第三种就是当程序启动时第一次开启的运行循环模式。第四种的话一般开发中没听到过。没有去研究过。其实还有一种占位模式。不过没什么太大用处。
方法列表的数据结构是什么?
struct objc_method_list
{
struct objc_method_list* method_next; /* 这个变量用来链接另一个单独的方法链表 */
int method_count; /* 结构中定义的方法数量 */
struct objc_method method_list[1]; /* 可变长度的结构 */
};
分类是如何实现的?它为什么会覆盖掉原来的方法?
因为分类方法加入类中这一操作是在运行期系统加载分类时完成的,运行期系统会把分类中所实现的每一个方法都加入类的方法列表中
- category的实例方法、协议以及属性添加到类上
- category的类方法和协议添加到类的metaclass上
category的方法被放到了新方法列表的前面,而原来类的方法被放到了新方法列表的后面,所以category的方法会“覆盖”掉原来类的同名方法。