论一次iOS面试

最近觉得现在所在公司平台用户量太少,自身技术已经到了一个瓶颈,是时候需要换一个用户量多的平台,好好研究下iOS的性能优化、内存优化等问题了。

所面试的公司由于一些默认的规定,就不多说了,大致是面了一个下午,从2点到下午6点半,正式拿到offer,先从笔试题开始说起吧。

笔试题:15道题,稍微有些多了,做了将近一个半小时。从笔试题就可以稍微看出一个公司的iOS团队技术水平如何,以及他们是不是真的想要招人。我春节之前投过一波简历,当时挑了一家公司去,还没技术面,只是看了他们的面试题,就知道了这个公司大概不会录用我,因为那面试题太水了,一看就是百度过来还没有筛选的。做完之后,面我的面试官就和我说,这套面试题从他入职以来到现在就没换过,我就呵呵了,明显是没招人的打算,叫我过来纯属浪费时间。

第一道,是C\OC\C++里面的一些常识吧,就是nil、Null、Nil的区别

这道题我答的不好,只是从C\OC语法的角度上解释了下它们的区别,回来百度下,看了其他人的回答,该这么写:

nil和null从字面意思来理解比较简单,nil是一个对象,而NULL是一个值,我的理解为nil是将对象设置为空,而null是将基本类型设置为空的,个人感觉有点像属性当中,基本类型分配为assign NSString类型一般分配copy,而对象一般用retain。而且我们对于nil调用方法,不会产生crash或者抛出异常。

nil是一个对象指针为空,Nil是一个类指针为空,NULL是基本数据类型为空。这些可以理解为nil,Nil, NULL的区别吧。

第二道,UIEvent与UITouch的异同

我当时的回答是,UIEvent对象包含一个UITouch对象,这是错误的。实际开发中,我经常用到touches系列API,但是基本没关注UIEvent对象:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [[touches anyObject] locationInView:self.view];
}

经常这么用,主要关注的是UITouch对象,谷歌过来,关于UITouch:

当用户手指触摸屏幕,就会创建一个与这根手指相关联的对象,一根手指对应一个UITouch对象,它保存着与手指相关的信息,比如手指触摸的位置、时间、阶段。

UIEvent对象:

每产生一个事件,就会产生一个UIEvent对象,它称为事件对象,记录事件产生的时刻和类型。

第三道,响应者链条,这是妥妥的送分题,不详细解释了。

第四道,好像是关于assign\copy\retain\nonatomic\atomic的使用场合吧,也算是送分题,需要注意的是,即使是atomic也不能保证线程安全的,这个我测试过,相应的资料谷歌下,应该有的。

第五道,好像是为什么delegate用assign,而不用retain,送分题,不解释。

第六道,就是说,一个autoreleasepool在什么时候被销毁?

如果不知道RunLoop机制,这里建议回答,在线程被销毁之前会销毁autoreleasepool,对pool立面的所有对象做一次release操作。

正确的回答,应该是在RunLoop进入休眠之前,会销毁pool,在RunLoop被唤醒时,会创建pool,但是,你既然这么写了,就要做好面试官问你RunLoop相关知识的准备。

第七、八、九、十道,基本就是MRC的内存管理,判断是否正确以及纠错。

比如说:

    NSString *name = [[NSString alloc] initWithString:@"lisi"];
    [name retain];
    [name release];
    [name autorealse];

需要在后面写出reationCount的值,一开始我比较蒙的是,autorealse到底在啥时候会对name进行一次release操作,然后想了下,要进行release操作,肯定是要这个RunLoop进入休眠时,而在这样一个状态,RunLoop并未进入休眠......

实际上也证明我是正确的:Autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当 前的Autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用Release。那么pool在啥时候被销毁?上面那个题目已经有解释了。

第十一、十二、十三道,貌似忘记了,不是送分题,但也没有很大难度的题,没啥印象了。

第十四、十五道,是算法题,第十四题,我没看懂出题人的意思?!看了好几遍,没看懂,唯一空白的一个题目。

第十五题,是将两个有序链表合并成一个有序链表,分分钟秒了它。

第一面,应该是iOS负责人。

大概聊了将近两个小时吧,挺认真负责的,技术非常好。他所提的比较有印象的面试问题:

1、RunLoop,于是我便把我理解的RunLoop详细说了说,大致就是下面这些东西:

RunLoop:运行循环,一个iOS程序的从main函数进入UIApplicationMain,UIApplicationMain就开启了一个RunLoop,这个RunLoop是主线程的RunLoop,也就是Main RunLoop,它的作用是让我们的OC程序一直运行。

实际上,我们可以把RunLoop认为是一个死循环,它在这个循环内,不断的休眠与重启,从而保持程序的运行,处理程序的各种事件。例如:

do
{
}while(1);

iOS中有两套API来使用和访问RunLoop,一个是Foundation下的NSRunLoop,一个是Core Foundation下的CFRunLoopRef,(NSRunLoop是基于CFRunLoopRef的一层OC包装)。

RunLoop与线程的关系:
每一个线程都有与之相对应的RunLoop,只有主线程的RunLoop是默认开启的,子线程的RunLoop需要我们手动开启。
RunLoop在第一次获取时创建,在线程结束时销毁。

[NSRunLoop CurrentRunLoop]

[NSRunLoop MainRunLoop]

CFRunLoopGetCurrent()
CFRunLoopGetMain()

Core Foundation中runLoop相关的五个类

CFRunLoopModeRef:
代表着RunLoop的运行模式,RunLoop在一个时间点只能运行一种模式,比如说要么是defaultMode,要么是TrackingMode

一个RunLoop包含若干个Mode,每个mode又包含若干个Source\Timer\observer

如果需要切换Mode,只能是先退出Loop,再重新指定一个Mode进入

这样做的目的主要是为了分割开不同组的Source/Timer/Observe,让他们互不影响。

CFRunLoopSourceRef :系统的一些点击、拖拽等事件,相当于一个事件源

CFRunLoopTimerRef : 定时器相关的处理

CFRunLoopObserverRef : 实际上,我们是可以监听RunLoop的活动的,比如说监听它是否开启、是否将要进入休眠等。

这两种RunLoop使我们在日常编程中经常用到的:
kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行

UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响

在OC中,几种常见的Mode
NSDefaultRunLoopMode 

UITrackingRunloopMode : 需要注意,这种模式下的Mode,是只能处理UIScrollView、或者继承自UIScrollView的对象的拖拽等事件的,也就是说,当UIScrollView在滚动的时候,是进入UITrackingRunloopMode,在默认条件下,Timer是添加在NSDefaultRunLoopMode下的,所以就不能处理Timer的相关事件。

(利用这样的一个特性,我们可以优化UITableView和UICollectionView的滚动,我们可以将图片的加载设置在NSDefaultRunLoop下,这样在滚动UITableView的时候,RunLoop会是UITrackingRunloopMode,就不会去加载图片,从而减少卡顿的现象出现,使得UI交互更加流畅)

还有一个NSRunLoopCommonMode,需要注意的是,它并不是真正的Mode,只是一个占位符

如果想要监听RunLoop状态的改变,有如下代码可以设置监听:
- (void)observer
{
    //创建observer
    CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        NSLog(@"监听到RunLoop状态发生改变 %zd", activity);
    });

    //添加监听者
    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);

    CFRelease(observer);
}

这是runLoop可以被监听的状态:
/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry = (1UL << 0),        //进入,也就是开启runloop了的时候
    kCFRunLoopBeforeTimers = (1UL << 1), //在处理所有定时器操作之前
    kCFRunLoopBeforeSources = (1UL << 2), //在处理所有source源(点击等事件)之前
    kCFRunLoopBeforeWaiting = (1UL << 5), //将要进入休眠状态
    kCFRunLoopAfterWaiting = (1UL << 6),  //将要苏醒的状态
    kCFRunLoopExit = (1UL << 7),         //退出runLoop
    kCFRunLoopAllActivities = 0x0FFFFFFFU   //以上所有的状态
};

@autoReleasePool在什么时候被释放?
它是在它所在的runLoop进入休眠时被释放,在runLoop再一次启动时创建。

当然,这些都是理论上的知识,实际中我们可以把imageView设置成在RunLoop的DefaultMode下显示,那么当UIScrollView,以及继承自UIScrollView的控件在拖拽的时候就不会显示ImageView,因为在滚动的时候,RunLoop是TrackingMode。

还可以开启一条常驻线程,这样就没必要多次创建子线程,造成性能上的损耗。

2、如果我们在开发中使用SDWebImage框架,会发现在UITableView滚动的停止的时候,它是优先下载显示在屏幕上的cell里面的图片的,这个效果如果让你来实现,你如何实现?

开发中我是经常使用SDWebImage框架的,但是没看过它的源代码,不过以前我做过不依赖SDWebImage框架的图片下载操作,那个时候是用NSOperation来实现的,还考虑到了重复下载的问题。

NSOperation是可以设置停止(暂停)的,这样的话,监听scrollView的滚动,当cell离开屏幕时,我们就把它设置为暂停下载状态,当它出现在屏幕时,再设置为开启下载状态。

面试官问我,是否还有其他的解决方案,(一脸蒙--)没有了。然后他提出了一种很好的解决方案,就是我们在设置并行队列的时候,是有一个优先值的,我们设置后面的image下载操作的优先级递增,这样的话,轻轻松松就解决了问题。

(好吧,我一直都在使用着默认的优先级,的确没考虑过这个问题,不过苹果文档也说了,建议开发者使用default优先级,因为如果优先级比较乱的话,可能会造成未知原因而导致程序崩溃,但这并不是理由,不知道就是不知道)。

3、问了下iOS里面工厂模式的使用场景,其实这个问题我在《Objective-C编程之道》上看到过,也知道它,但是那一瞬就是脑海一片空白,好吧,然后面试官和我说了,比如UIButton的类方法创建,里面是黑箱的,我们只是知道它会返回一个啥样类型button回来,类似的,NSValues等。(不得不说是幸运啊,刚好这个问题,在移动端负责人面我时候,我就举了这样的例子)

4、有三个网络请求需要发送,等三个网络请求发送完之后,要更新UI,怎么操作可以节省时间?

我第一个回答,觉得是直接使用dispatch_group来搞就好,不过面试官提醒了下我,就是一个网络请求发送完毕之后,等待数据返回还要一段时间,所以,dispatch_group是不行的。

然后,我觉得貌似只能一条条发送了,认真的想了下,其实是可以设置一个int属性,来记录是否都返回数据成功了,如果成功,就++,然后用kvo来监听这个属性就好。(当时回答是这么回答的,实际上应该用不到kvo来监听,可以直接重写该属性的setter方法)

还有其他的问题吧,不过印象不是很深刻了。

移动端负责人面试:

1、至此,第一面算是过了,心中松了一口气。这位面试官进来,先是问了我,iOS程序启动这之间的一系列过程,我回答的比较简单,从main->UIApplicationMain来开启一个主运行循环->Main RunLoop 开始处理各种source\observe\timer,从一个Mode到另一个Mode,然后调用appDelegate里面的application didFinish....那方法,进入KeyWindow......

2、把你所知道的设计模式其中思想都说说,举例说下应用场景

差点跪了,以前在看设计模式的时候,那理论太多了,记不住啊。然后只说出九种模式的思想,勉强算是过关了。

3、把所知道的排序算法手写出来

我在想,还好不是面试官来定某些算法,我所知道的并且能写的,冒泡、选择、快速、归并,写了下,算是过关了。

技术总监\经历面试

就是一个算法题,一个人上台阶,一次可以走一阶,走两阶,走三阶,那么如果有n阶,走法有多少种?

递推题,根据前面的规律,可以很容易推出,f(n) = f(n-1) + f(n-2) +f(n-3),然后用c语言把它写出来了。

之后就是人事面,顺利拿到offer。

ps:我辞职报告已经提交了,公司让我帮他面试iOS人员,我想说,那些培训的,写两年iOS工作经验,竟然和我说没学过C?对C不熟?作为一个计算机专业毕业的人,做数据结构的题,20道只正确7道,我去。这一行现在是有多乱,开的工资,10~~15k,还有一个15~~25k!真的是无知者无畏么?

时间: 2024-10-29 19:11:24

论一次iOS面试的相关文章

iOS面试

高德iOS面试整理(顺序有些乱,一面跪了) 1.简单自我介绍 2.聊c语言 3.两个数比较大小不用if和三目运算符 4.int转化为bit数组 5.多态和隐藏 6.const 和define区别 7.String类实现拷贝构造函数注意事项,是否有必要重写 数据结构 1.树层次遍历 2.链表删除 iOS 1.通知和delegate 2.ViewController 生命周期,  手动代码View添加 3.iOS 的click事件的响应过程 4.通知和KVO比较 5.ARC和非ARC (问到静态分析

iOS 面试问题的解答

关于一些 iOS 面试问题的解答 2015年04月26日 这篇 post 主要是对知乎上 iOS程序员的问题列表 的回答, 也算是对自己已有的知识进行整理. 如果你对本篇 post 中的回答有所疑问, 可以在下面留言. 如果有问题, 我一定会修改的 :-) 问题以及回答 1. 什么是 ARC? (ARC 是为了解决什么问题而诞生的?) ARC 是 Automatic Reference Counting 的缩写, 即自动引用计数. 这是苹果在 iOS5 中引入的内存管理机制. Objective

C C++ OC iOS面试重点问题(一)

C C++ OC iOS面试重点问题(一) 1.字符串常量需要加\0 2.逻辑运算 位操作(经典:实现两个数的交换) 3.关键字 4.引用和指针的区别和联系 5.如何引用一个已经定义过的全局变量?  答:可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变变量,假定你将那个变量写错了,那么在编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错. 5.extern关键字的用法? 答:ext

[转] 上级向的十个iOS面试问题

上级向的十个iOS面试问题 转自 http://onevcat.com/2013/04/ios-interview/ 不管对于招聘和应聘来说,面试都是很重要的一个环节,特别对于开发者来说,面试中的技术问题环节不仅是企业对应聘者技能和积累的考察,也是一个开发者自我检验的好机会.对于iOS和Mac开发来说,因为本事还算比较新,企业对于这方面的开发者需求也比较大,所以面试时的要求可能并不是很高,一般能知道一些Cocoa和OC的基本知识也就认为可以了.但是对于一个希望拥有技术力基础的企业的iOS或者Ma

李洪强iOS面试一般性问题

iOS面试一般性问题,学会这些拿offer几率提升90%! 面试题中有一些一般性的问题,通常是会问到的.面试iOS应聘者时,切入点很重要,不同的切入点会导致不同的结果,没有找到合适的切入点也无法对应聘者有一个全面的了解.所以下面的面试问题更多的是提供方向,没有固定的答案,而且可以根据应聘者的回应引出更多有意思深层次的讨论. 注意:以下问题的参考答案均为笔者所答,不代表正确,问题答案因人而异,请根据自己的实际情况回答,若认为不合理,请在评论中指出.下面所有的参考答案,都是笔者站在面试官的角度来分析

iOS面试宝典

前言 本篇文章总结多年来iOS开发人员面试常问到的问题,也希望能够带领刚入门的同志们走入职场.在准备去面试之前,你觉得自己到底有几斤几两呢?看看下面的问题吧!!! 新手必看 下面的文章是笔者推荐大家阅读的: iOS学习路线 iOS开发必懂 做好面试的准备 在收到通知到xxxx公司面试前,我们应该好好阅读下面的文章,做好充分的准备,不打无准备之仗. 我也面试过不少同学,在与他们的交谈中可以看出准备不足,面对一个个简单的问题,答非所问或者说了半天没有说到点上,于是给面试官一种菜鸟的形象. 本人只是本

ios面试技术要点

iOS面试 技术总结点(可参考):多线程 运行时 runloop app框架 几种动画编程 jsonmodel原理 sdwebimage原理 masonry怎么应用及原理 应用框架有哪些 说一下Facebook的flux框架 混合app原理 怎么优化内存 怎么用instruments优化动画效果  KVC/KVO的理解及运用 本地存储的几种方式CoreData问的最多https://www.zhihu.com/question/19604641 这里面很多问题都问过了https://www.zh

ios 面试基础问题

转自http://www.jianshu.com/p/9c83145bb4ba iOS面试 字数2396 阅读2097 评论4 喜欢93 1.#import和#include的区别,@class代表什么? @class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文件中还是需要使用#import 而#import比起#include的好处就是不会引起重复包含 2.谈谈Object-C的内存管理方式及过程? 1.当你使用new,alloc和copy方法创建一个对象时,该对象的保留计数器

iOS 面试集锦2

4.写一个setter方法用于完成@property (nonatomic,retain)NSString *name,写一个setter方法用于完成@property(nonatomic,copy)NSString *name - (void) setName:(NSString*) str { [str retain]; [name release]; name = str; } - (void)setName:(NSString *)str { id t = [str copy]; [na

iOS 面试(高德)

高德iOS面试整理(顺序有些乱) 确实挺对不住面试官的,视频面试,我的这边始终没声音. 1. - (void)testFun { CGRect a ; //-.. } a的内存在堆上,还是栈上? 2.. 如何把一个 CGRect类型的数据放在堆上去? 你能够想到多少种方法? 3.  CGRect a ; [a retain]; 是否能通过编译 4.autorelease pool有用过吗? 对于auto release pool,同一个thread 可以存在多个auto release pool