目录
1.你使用过Objective-C的运行时编程(Runtime Programming)么?如果使用过,你用它做了什么?你还能记得你所使用的相关的头文件或者某些方法的名称吗?
Objecitve-C的重要特性是Runtime(运行时),在#import <objc/runtime.h>下能看到相关的方法,用过objc_getClass()和class_copyMethodList()获取过私有API;
使用
Method method1 = class_getInstanceMethod(cls, sel1);
Method method2 = class_getInstanceMethod(cls, sel2);
method_exchangeImplementations(method1, method2);
2.你实现过多线程的Core Data么?NSPersistentStoreCoordinator,NSManagedObjectContext和NSManagedObject中的哪些需要在线程中创建或者传递?你是用什么样的策略来实现的?
待整理!
3.Core开头的系列的内容。是否使用过CoreAnimation和CoreGraphics。UI框架和CA,CG框架的联系是什么?分别用CA和CG做过些什么动画或者图像上的内容。(有需要的话还可以涉及Quartz的一些内容)
待整理
4.是否使用过CoreText或者CoreImage等?如果使用过,请谈谈你使用CoreText或者CoreImage的体验。
-
CoreText
可以解决复杂文字内容排版问题。 -
CoreImage
可以处理图片,为其添加各种效果。体验是很强大,挺复杂的。
5.NSNotification和KVO的区别和用法是什么?什么时候应该使用通知,什么时候应该使用KVO,它们的实现上有什么区别吗?如果用protocol和delegate(或者delegate的Array)来实现类似的功能可能吗?如果可能,会有什么潜在的问题?如果不能,为什么?(虽然protocol和delegate这种东西面试已经面烂了…)
-
NSNotification
是通知模式在iOS的实现 -
KVO
的全称是键值观察(Key-value observing),其是基于KVC(key-value coding)的 -
KVC
是一个通过属性名访问属性变量的机制。 - 例如将Module层的变化,通知到多个Controller对象时,可以使用NSNotification;如果是只需要观察某个对象的某个属性,可以使用KVO。
6.你用过NSOperationQueue么?如果用过或者了解的话,你为什么要使用NSOperationQueue,实现了什么?请描述它和GCD的区别和类似的地方(提示:可以从两者的实现机制和适用范围来描述)。
NSOperationQueue
- 使用NSOperationQueue用来管理子类化的NSOperation对象,控制其线程并发数目。
- GCD和NSOperation都可以实现对线程的管理,区别是NSOperation和NSOperationQueue是多线程的面向对象抽象。项目中使用NSOperation的优点是NSOperation是对线程的高度抽象,在项目中使用它,会使项目的程序结构更好,子类化NSOperation的设计思路,是具有面向对象的优点(复用、封装),使得实现是多线程支持,而接口简单,建议在复杂项目中使用。
GCD
项目中使用GCD的优点是GCD本身非常简单、易用,对于不复杂的多线程操作,会节省代码量,而Block参数的使用,会是代码更为易读,建议在简单项目中使用。
5.既然提到GCD,那么问一下在使用GCD以及block时要注意些什么?它们两是一回事儿么?block在ARC中和传统的MRC中的行为和用法有没有什么区别,需要注意些什么?如何避免循环引用?
- 使用block是要注意,若将block做函数参数时,需要把它放到最后
- GCD是Grand Central Dispatch,是一个对线程开源类库,而Block是闭包,是能够读取其他函数内部变量的函数
7.您是否做过异步的网络处理和通讯方面的工作?如果有,能具体介绍一些实现策略么?
待整理
8.对于Objective-C,你认为它最大的优点和最大的不足是什么?对于不足之处,现在有没有可用的方法绕过这些不足来实现需求。如果可以的话,你有没有考虑或者实践过重新实现OC的一些功能,如果有,具体会如何做?
- 最大的优点是它的运行时特性
- 不足是没有命名空间,对于命名冲突,可以使用长命名法或特殊前缀解决,如果是引入的第三方库之间的命名冲突,可以使用link命令及flag解决冲突。
9.如何获取通讯录数据
从通讯录数据库查询联系人数据是无法使用SQL语句,只能通过ABAddressBookCopyArrayOfAllPeople、ABAddressBookCopyPeopleWithName来获得。ABAddressBookCopyArrayOfAllPeople函数是通过人名查询通讯录中的联系人,其中的name参数是查询的前缀关键字。
10.NSURLConnection类的同步请求方法?
A.+sendSynchronousRequest:returningResponse:error:
B.-initWithRequest:delegate:
C.-initWithRequest:delegate:startImmediately:
理解:B和C都是异步方法,需要设置delegate属性。
10.genstrings命名的语法
genstrings [-a] [-q] [-o <outputDir>] sourcefile
其中参数:
-a:在存在的文件后面追加内容;
-q:关闭多个键值对的警告;
-o:指定输出目录
因此如果我们想输出到en.lproj目录,则代码如下:
genstrings -o en.lproj *.m
11.判断是否为iPad设备
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad){....}
12.Objective-C有哪几种内存管理方法?
-
MRR(Manual Retain Release)
- MRC的官方名字; -
MRC(Manual Reference Counting )
- 手动引用计数; -
ARC(Automatic Reference Counting)
- 自动引用计数; -
GC(Garbage Collection)
- 是垃圾回收(在开发OS X中使用)
13.iOS中持久化方式有哪些?
- 属性列表文件
- 对象归档
- SQLite数据库
- CoreData
14.关于类别的理解
类别是一种为现有的类添加新方法的方式。利用Objective-C的动态运行时分配机制,Category提供了一种比继承更为简洁的方法来对class进行扩展,无需创建对象类的子类就能为现有的类添加新方法,可以为任何已经存在的class添加方法,包括那些没有源代码的类(比如某些框架类),但不能删除修改之前的方法。
类别主要有3个作用:
可以将类的实现分散到多个不同文件或多个不同框架中,方便代码管理。也可以对框架提供类的扩展(没有源码,不能修改)。
创建对私有方法的前向引用。如果其他类中的方法未实现,在你访问其他类的私有方法时编译器报错。这时使用类别,在类别中声明这些方法(不必提供方法实现),编译器就不会产生警告。
向对象添加非正式协议:创建一个NSObject的类别成为“创建一个非正式协议”,因为可以作为任何类的委托对象使用。
15.NSRunLoop的以下描述错误的是
A. RunLoop并不是由系统自动控制的;
B.有3类对象可以被run loop监控:sources,timer,observers
C.线程是默认启动run loop的;
D.NSTimer可手动添加到新建的NSRunLoop中。
理解
A
:Runloop的作用在于当有事情要做时它使当前的thread工作,没有事情做时又使thread休眠。Runloop并不是由系统自动控制的,尤其是对那些新建的次线程需要对其进行显示的控制。B
:有三类对象可以被run loop监控,source,timer,observers。C
:每一个线程都有自己的runloop,主线程是默认开启的,创建的子线程是要手动开启的,因为NSApplication只启动main application thread.D
:NSTimer默认添加到当前NSRunLoop中,也可以手动指定添加到自己新建的NSRunLoop中。
16.常用的设计模式
- 单例模式
- 组合模式
- 观察者模式
- 代理模式
- 享元模式
- 工厂方法模式
- 抽象工厂模式
17.MVC的理解
数据管理者(M)、数据展示者(V)、数据加工者(C)
- M应该做的事:
- 给ViewController提供数据
- 给ViewController存储数据提供接口
- 提供经过抽象的业务基本组件,供Controller调度
- C应该做的事:
- 管理View Container的生命周期
- 负责生成所有的View实例,并放入View Container
- 监听来自View与业务有关的事件,通过与Model的合作,来完成对应事件的业务。
- V应该做的事:
- 响应与业务无关的事件,并因此引发动画效果,点击反馈(如果合适的话,尽量还是放在View去做)等。
- 界面元素表达
18.MVC和MVVM的区别
- MVVM是对胖模型进行的拆分,其本质是给控制器减负,将一些弱业务逻辑放到VM中处理
- MVC是一切设计的基础,所有新的设计模式都是基于MVC进行的改进
- 补充:常见的设计模式有:MVC、MVCS、MVVM、viper
19.TCP和UDP有什么区别?
- TCP是面向连接的,建立连接需要经历三次握手,保证数据正确性和数据顺序
- UDP是非连接的协议,传送数据受生成速度,传输带宽等限制,可能造成丢包
- UDP一台服务端可以同时向多个客户端传输信息
- TCP报头体积更大,对系统资源要求更多
20.TCP的三次握手
- 第一次握手:客户端发送syn包到服务器,并进入
syn_send
状态,等待服务器进行确认; - 第二次握手:服务器收到客户端的syn包,必须确认客户的SYN,同时自己也发送一个SYN包,即SYN + ACK包,此时服务器进入
SYN_RECV
状态; - 第三次握手:客户收到服务器发送的SYN+ACK包之后,向服务器发送确认包,此包发送完毕,客户端和服务器进入
ESTABLISHED
状态,完成第三次握手。
21.如何制作一个静态库/动态库?他们的区别是什么?
- Xcode6支持制作静态库/动态库framework
- 无论是动态库还是静态库都是区分真机和模拟器的
- 静态库编译静态库文件装入程序空间,动态库是文件动态装入内存
- 动态库执行到相关函数才会被调用,节省空间
- 苹果一般不允许第三方动态库,APP容易被拒
- 一个lib包含了很多的架构,会打到最后的包里么?
- 不会,如果lib中有armv7, armv7s, arm64, i386,x86_64架构,而target architecture选择了armv7s,arm64,那么只会从lib中link指定的这两个架构的二进制代码,其他架构下的代码不会link到最终可执行文件中;反过来,一个lib需要在模拟器环境中正常link,也得包含i386架构的指令
每一个设备都有属于自己的CPU架构
每一个静态支持的架构是固定
-
模拟器
- 4s-->5 : i386
- 5s-->6plus : x86_64
-
真机
- 3gs-->4s : armv7
- 5/5c : armv7s,静态库只要支持了armv7,就可以跑在armv7s的架构上
- 5s-->6plus : arm64
常用命令总结:
使用lipo -info命令,查看指定库支持的架构,比如UIKit框架
lipo -info UIKit.framework/UIKit
想看的更详细的信息可以使用lipo -detailed_info
lipo -detailed_info UIKit.framework/UIKit
还可以使用file命令
file UIKit.framework/UIKit
合并MyLib-32.a和MyLib-64.a,可以使用lipo -create命令合并
lipo -create MyLib-32.a MyLib-64.a -output MyLib.a
22.支持64-bit后程序包会变大么?
会,支持64-bit后,多了一个arm64架构,理论上每个架构一套指令,但相比原来会大多少还不好说
23.用过Core Data或者SQLite吗?读写是分线程的吗?遇到过死锁没?如何解决的?
- 用过SQLite,使用FMDB框架
- 丢给FMDatabaseQueue或者 添加互斥锁(NSLock/@synchronized(锁对象))
24.APNS的原理:
- 应用在通知中心注册,由iOS系统向APNS请求返回设备令牌(device Token)
- 应用程序接收到设备令牌并发送给自己的后台服务器
- 服务器把要推送的内容和设备发送给APNS
- APNS根据设备令牌找到设备,再由iOS根据APPID把推送内容展示