之前发了这篇iOS面试总结(2020年6月),没想到挺受大家欢迎,本来是没打算为它写答案,但有几个人建议我最好出一篇答案,提的人多了我就答应了下来。因为最近比较忙,断断续续总算补完了,就有了这篇文章,希望它对大家还有用处。这些都属于参考答案,如果大家感觉有不对不准确的地方也欢迎指出,我会及时更新。
关于面试题
打个比方,如果把找工作理解成考大学,面试就是高考,市面上的“真题”就是模拟试卷。我们会很容易倾向于在面试前寻找对应公司的面试“真题”,重点准备,期待“押题”成功。但实际上,即使面试同一家公司,它会有不同部门,不同业务线,不同面试官,即使遇到同一面试官,他也不一定就每次考察完全一样的内容。想想高考中那些考的好的同学,他们肯定不是靠“押题”才能取得好成绩吧,他们大多靠的是平常积累及对知识点灵活掌握,那面试也一样啊。执着于搜题,把面试题当做重点进行“复习”,还不如自己划出“考纲”,各个知识点逐一检查掌握情况,复习的更全面呢。
我对于面试题的看法一直是相对保守的,这类文章一般只是内容搬运,它会存在一些偏差和误读,最重要的那就是几道题往那一扔,并没有产出有价值的东西。这也是为什么我上篇面试总结,会加了一些面试技巧,整理面试题时,也没提他们是出自哪家公司,就是不希望大家把题目区别看待。
说了这些并不是说面试题没用啊,而是希望大家不要迷信面试题,更多地去关注那些有质量有深度的技术文章。面试考核的是知识点而不是具体的某些题目,面试题的作用在于,衡量我们的知识掌握情况,便于我们查漏补缺,越说越像是针对一次“考试”了😄。
总结不易,希望这份参考答案能对你有所帮助,如果想持续关注我,欢迎订阅微信公众号:iOS成长之路。
面试题及参考答案
Swift
1、Swift中struct和class有什么区别?
struct是值引用,更轻量,存放于栈区,class是类型引用,存放于堆区。struct无法继承,class可继承。
2、Swift中的方法调用有哪些形式?
答:直接派发、函数表派发、消息机制派发。派发方式受声明位置,引用类型,特定行为的影响。为什么Swift有这么多派发形式?为了效率。
参考文章:深入理解 Swift 派发机制
3、Swift和OC有什么区别?
Swift和OC的区别有很多,这里简要总结这几条:
Swift | Objective-C | |
---|---|---|
语言特性 | 静态语言,更加安全 | 动态语言,不那么安全 |
语法 | 更精简 | 冗长 |
命名空间 | 有 | 无 |
方法调用 | 直接调用,函数表调用,消息转发 | 消息转发 |
泛型/元组/高阶函数 | 有 | 无 |
语言效率 | 性能更高,速度更快 | 略低 |
文件特性 | .swift 单文件 | .h/.m包含头文件 |
编程特性 | 可以更好的实现函数式编程/响应式编程 | 面向对象编程 |
4、从OC向Swift迁移的时候遇到过什么问题?
可以参考这篇文章:OC项目转Swift指南 里的混编注意事项。
5、怎么理解面向协议编程?
面向对象是以对象的视角观察整体结构,万物皆为对象。
面向协议则是用协议的方式组织各个类的关系,Swift底层几乎所有类都构建在协议之上。
面向协议能够解决面向对象的菱形继承,横切关注点和动态派发的安全性等问题。
OC语法
1、Block是如何实现的?Block对应的数据结构是什么样子的?__block的作用是什么?它对应的数据结构又是什么样子的?
block本质是一个对象,底层用struct实现。
数据结构如下:
struct Block_descriptor {
unsigned long int reserved;
unsigned long int size;
void (*copy)(void *dst, void *src);
void (*dispose)(void *);
};
struct Block_layout {
void *isa;
int flags;
int reserved;
void (*invoke)(void *, ...);
struct Block_descriptor *descriptor;
/* Imported variables. */
};
-
isa 指针,所有对象都有该指针,用于实现对象相关的功能。
-
flags,用于按 bit 位表示一些 block 的附加信息,本文后面介绍 block copy 的实现代码可以看到对该变量的使用。
-
reserved,保留变量。
-
invoke,函数指针,指向具体的 block 实现的函数调用地址。
-
descriptor, 表示该 block 的附加描述信息,主要是 size 大小,以及 copy 和 dispose 函数的指针。
-
variables,capture 过来的变量,block 能够访问它外部的局部变量,就是因为将这些变量(或变量的地址)复制到了结构体中。
__block
的作用是可以获取对应变量的指针,使其可以在block内部被修改。通过反编译的代码我们可以看到该对象是这样的:
struct __Block_byref_i_0 {
void *__isa;
__Block_byref_i_0 *__forwarding;
int __flags;
int __size;
int val; //变量名
};
对于block的深入了解,可以参考《Objective-C高级编程》第二章或者唐巧的这篇谈Objective-C block的实现
2、GCD中的Block是在堆上还是栈上?
堆上。可以通过block的isa指针确认。
3、NSCoding协议是干什么用的?
一种编码协议,归档时和解档时需要依赖该协议定义的编码和解码方法。Foundation和Cocoa Touch中的大部分类都遵循了这个协议,一般被NSKeyedArchiver做自定义对象持久化时使用。
4、KVO的实现原理
利用Runtime生成一个中间对象,让原对象的isa指针指向它,然后重写setter方法,插入willChangeValueForKey和didChangeValueForKey方法。当属性变化时会调用,会调用这两个方法通知到外界属性变化。
5、NSOperation有哪些特性,比着GCD有哪些优点,它有哪些API?
NSOperation是对GCD的封装,具有面向对象的特点,可以更方便的进行封装,可以设置依赖关系。
API可以查看NSOperation文档。
6、NSNotificaiton是同步还是异步的,如果发通知时在