面试问题一般按照三种思路去问,第一种是网络上流传的常见面试问题,第二种是根据应聘者的简历,挑选主题深入下去,第三种是面试者自己感兴趣的问题或者说是经验总结
第一部分:来自网络上的
iOS数据持久化存储方案有哪些?
- plist属性列表存储(如NSUserDefaults)
- 文件存储(如二进制数据写入文件存储,通过NSFileManager来操作将下载起来的二进制数据写入文件中存储)
- NSKeydeArchiver归档存储,
- 数据库SQLite3存储(如FMDB、Core Data)
- KeyChain,用户名密码
沙盒的目录结构是怎样的?各自一般用于什么场合?
- Application:存放程序源文件,上架前经过数字签名,上架后不可修改
- Documents: 保存应⽤运行时生成的需要持久化的数据,iTunes同步设备时会备份该目 录。例如,游戏应用可将游戏存档保存在该目录
- tmp: 保存应⽤运行时所需的临时数据,使⽤完毕后再将相应的文件从该目录删除。应用 没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时 不会备份该目录
- Library/Caches: 保存应用运行时⽣成的需要持久化的数据,iTunes同步设备时不会备份 该目录。⼀一般存储体积大、不需要备份的非重要数据,比如网络数据缓存存储到Caches下
- Library/Preference: 保存应用的所有偏好设置,如iOS的Settings(设置) 应⽤会在该目录中查找应⽤的设置信息。iTunes同步设备时会备份该目录
常见的出现内存循环引用的场景有哪些?
- 定时器(NSTimer):NSTimer经常会被作为某个类的成员变量,而NSTimer初始化时要指定self为target,容易造成循环引用(self->timer->self)。 另外,若timer一直处于validate的状态,则其引用计数将始终大于0,因此在不再使用定时器以后,应该先调用invalidate方法
- block的使用:block在copy时都会对block内部用到的对象进行强引用(ARC)或者retainCount增1(非ARC)。在ARC与非ARC环境下对block使用不当都会引起循环引用问题, 一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,简单说就是self.someBlock = Type var{[self dosomething];或者self.otherVar = XXX;或者_otherVar = …};出现循环的原因是:self->block->self或者self->block->_ivar(成员变量)
- 代理(delegate):在委托问题上出现循环引用问题已经是老生常谈了,规避该问题的杀手锏也是简单到哭,一字诀:声明delegate时请用assign(MRC)或者weak(ARC),千万别手贱玩一下retain或者strong,毕竟这基本逃不掉循环引用了!
Block中weakSelf和strongSelf作用是什么?
__weak __typeof(self)weakSelf = self;
[self.context performBlock:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doMoreThing];
} ];
用weakSelf是为了不让Block增加引用计数,使self可以顺利释放
用strongSelf是为了防止事情还没做完,weakSelf就变成了nil
使用Block时何时需要WeakSelf和StrongSelf?
MD5和Base64的区别是什么,各自使用场景是什么?
- MD5:是一种不可逆的摘要算法,用于生成摘要,无法逆着破解得到原文。常用的是生成32位摘要,用于验证数据的有效性。比如,在网络请求接口中,通过将所有的参数生成摘要,客户端和服务端采用同样的规则生成摘要,这样可以防篡改。又如,下载文件时,通过生成文件的摘要,用于验证文件是否损坏。
- Base64:属于加密算法,是可逆的,经过encode后,可以decode得到原文。在开发中,有的公司上传图片采用的是将图片转换成base64字符串,再上传。在做加密相关的功能时,通常会将数据进行base64加密/解密。
发送10个网络请求,然后再接收到所有回应之后执行后续操作,如何实现?
从题目分析可知,10个请求要全部完成后,才执行某一功能。比如,下载10图片后合成一张大图,就需要异步全部下载完成后,才能合并成大图。
做法:通过dispatch_group_t来实现,将每个请求放入到Group中,将合并成大图的操作放在dispatch_group_notify中实现。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{ /*加载图片1 */ });
dispatch_group_async(group, queue, ^{ /*加载图片2 */ });
dispatch_group_async(group, queue, ^{ /*加载图片3 */ });
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 合并图片
});
iOS与H5交互的方式有哪些?
- 通过协议在shouldStartRequest中捕获请求,获取scheme来判断预先定义的功能,然后调用native代码。比如,定义点击图片调用native来展示大图,那么js接收到点击时,重定向将图片的url添加上自定义scheme
- 通过iOS7以后引入的JavaScriptCore框架来实现,通过注入对象的方式来实现,维护起来更简单。
- iOS引入的Webkit框架,使用WKWebView,而不是UIWebView
- 通过WebViewJavascriptBridge这个第三方库来实现
http的post和get的区别?
- GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连,如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD。如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。
- POST把提交的数据则放置在是HTTP包的包体中。
GCD里面有哪几种Queue?
- 主队列 dispatch_main_queue(); 串行 ,更新UI
- 全局队列 dispatch_global_queue(); 并行,四个优先级:background,low,default,high
- 自定义队列 dispatch_queue_t queue ; 可以自定义是并行:DISPATCH_QUEUE_CONCURRENT或者串行DISPATCH_QUEUE_SERIAL
UIView和CALayer的关系?
- UIView是iOS系统中界面元素的基础,所有的界面元素都继承自它。它本身完全是由CoreAnimation来实现的。它真正的绘图部分,是由一个叫CALayer(Core Animation Layer)的类来管理。 UIView本身,更像是一个CALayer的管理器,访问它的跟绘图和跟坐标有关的属性,例如frame,bounds等 等,实际上内部都是在访问它所包含的CALayer的相关属性。
- UIView有个layer属性,可以返回它的主CALayer实例,UIView有一个layerClass方法,返回主layer所使用的 类,UIView的子类,可以通过重载这个方法,来让UIView使用不同的CALayer来显示,例如通过
- (class) layerClass {
return ([CAEAGLLayer class]);
}
使某个UIView的子类使用GL来进行绘制。
- UIView的CALayer类似UIView的子View树形结构,也可以向它的layer上添加子layer,来完成某些特殊的表 示。例如下面的代码
grayCover = [[CALayer alloc] init];
grayCover.backgroundColor = [[[UIColor blackColor] colorWithAlphaComponent:0.2] CGColor];
[self.layer addSubLayer: grayCover];
会在目标View上敷上一层黑色的透明薄膜。
@synthesize和@dynamic分别有什么作用?
- @synthesize的语义是如果你没有手动实现setter方法和getter方法,那么编译器会自动为你加上这两个方法。
- @dynamic告诉编译器:属性的setter与getter方法由用户自己实现,不自动生成。假如一个属性被声明为@dynamic var,然后你没有提供@setter方法和@getter 方法,编译的时候没问题,但是当程序运行到 instance.var = someVar,由于缺setter方法会导致程序崩溃;或者当运行到someVar = var 时,由于缺getter方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。
下面的代码输出什么?
@implementation Son : Father
- (id)init {
self = [super init];
if (self) {
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
// 输出
NSStringFromClass([self class]) = Son
NSStringFromClass([super class]) = Son
这个题目主要是考察关于Objective-C中对self和super的理解。我们都知道:self是类的隐藏参数,指向当前调用方法的这个类的实例。那super呢?
很多人会想当然的认为“super和self类似,应该是指向父类的指针吧!”。这是很普遍的一个误区。其实 super是一个 Magic Keyword,它本质是一个编译器标示符,和self 是指向的同一个消息接受者!他们两个的不同点在于:super会告诉编译器,调用class 这个方法时,要去父类的方法,而不是本类里的。
上面的例子不管调用[self class]还是[super class],接受消息的对象都是当前 Son *xxx 这个对象。
当使用self调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用super时,则从父类的方法列表中开始找。然后调用父类的这个方法。
在滑动页面上的列表时,timer会暂定回调,为什么?如何解决?
如果我们把一个NSTimer
对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
添加到主运行循环中的时候, ScrollView滚动过程中会因为mode切换为UITrackingRunLoopMode
,而导致NSTimer将不再被调度。
将NSTimer 的mode 设置为NSRunLoopCommonModes(kCFRunLoopCommonModes)
可以解决这个问题。
// 将timer添加到NSDefaultRunLoopMode中
// 默认会自动添加到Run Loop中,但是mode为NSDefaultRunLoopMode
[NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(timerTick:)
userInfo:nil
repeats:YES];
// 先添加定时器
// 默认会自动添加到Run Loop中,但是mode为NSDefaultRunLoopMode
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0
target:self
selector:@selector(timerTick:)
userInfo:nil
repeats:YES];
// 手动修改其mode为forMode:NSRunLoopCommonModes
// 在滚动时,定时器也可以正常回调了
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
是否能通过 Category 给已有的类添加成员变量?
静态添加时不可以的,不能通过编译,但是可以动态添加。
func objc_getAssociatedObject(object: AnyObject!, key: UnsafePointer ) -> AnyObject!func objc_setAssociatedObject(object: AnyObject!, key: UnsafePointer, value: AnyObject!, policy: objc_AssociationPolicy)
iOS中级面试题一
iOS中级面试题二
知乎上的一个怎么面试iOS工程师的问题
第二部分:根据应聘者的简历
自我介绍,职业发展规划
- 学校,工作年限,公司背景,iOS相关的工作年限(2010年以前的都是先驱型的)
- 判断技术偏好型,还是技术加管理
- 看语言表达能力,沟通能力
- 是否积极向上,正能量
想离开的原因,选择新公司的理由
- 是否稳定
- 是否客观
- 动机是否正能量
印象深刻的项目经历
- 项目规模,产品特色
- 技术选型,团队合作
- 负责那一块,技术难点,如何克服
看什么书,看谁的博客,技术网站,gitHub上有没有源码,写自己的博客吗?
- 唐巧,王巍等
- Stack overflow, CocoaChina,V2EX
第三部分:本人关心的一些问题
基本上喜欢问一些开发式的问题,技术选择以及理由,发展方向的判断,使用的感受、经验等等。无所谓对错,仅仅是探讨,交流
界面开发技术的选择?
- Storyboard
- xib
- 代码
- AutoLayout / SizeClass SnapKit/Masonry
Swift和Object-C有什么不同?
- Swift是静态语言,Object-C是动态语言
- Swift分面向对象和结构化两部分,Object-C面向对象
- 可选类型
- Public、internal、private关键字
数据库的选择?
- FMDB ccgus/fmdb
- CoreData magicalpanda/MagicalRecord
- 直接SqlLite C API
如何做Cache?
- NSURLCache
- 数据库
- 序列化
界面性能优化
- CPU,GPU,60帧每秒
- 异步UIView绘制和渲染
- ibireme/YYAsyncLayer
- facebook/AsyncDisplayKit
一些常用的第三方库
Object-C
- AFNetworking/AFNetworking
- rs/SDWebImage
- SnapKit/Masonry
- ReactiveCocoa/ReactiveCocoa
- bang590/JSPatch
- react-native
Swift
- Alamofire/Alamofire
- SnapKit/SnapKit
- ReactiveX/RxSwift
Runtime的原理,常见使用场景
- 发送消息,@Select是字符串,对应函数指针,实现动态特性
- 本质都是C的struct和函数指针
- 自动字典转模型,利用属性列表字段
- 实现NSCoding协议,利用属性列表字段
- 方法替换,利用SEL和IMP之间的对应关系steipete/Aspects