iOS面试题分析
iOS面试
Model层:
-
数据持久化存储方案有哪些?
- plist(XML属性列表归档)
- 偏好设置
- NSKeydeArchiver归档(存储自定义对象)
- SQLite3(数据库,关系型数据库,不能直接存储对象,要编写一些数据库的语句,将 对象拆开存储)
- Core Data(对象型的数据库,把内部环节屏蔽)
-
沙盒的目录结构是怎样的?各自一般用于什么场合?
- Application:存放程序源文件,上架前经过数字签名,上架后不可修改 - Documents:保存应⽤运行时生成的需要持久化的数据,iTunes同步设备时会备份该目 录。例如,游戏应用可将游戏存档保存在该目录 - tmp:保存应⽤运行时所需的临时数据,使⽤完毕后再将相应的文件从该目录删除。应用 没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时 不会备份该目录 - Library/Caches:保存应用运行时⽣成的需要持久化的数据,iTunes同步设备时不会备份 该目录。⼀一般存储体积大、不需要备份的非重要数据 - Library/Preference:保存应用的所有偏好设置,iOS的Settings(设置) 应⽤会在该⺫录中 查找应⽤的设置信息。iTunes同步设备时会备份该目录
-
SQL语句问题:inner join、left join、right join的区别是什么?
- 内连接:inner join 或者 join (显示的是左右表都有完整字段值的记录)
- 左外连接:left outer join (保证左表数据的完整性)
-
sqlite的优化
- 不知道
-
网络通信用过哪些方式(100%的人说了AFNetworking...)
-
使用苹果自带类 NSURLCollection,xcode7已经被NSURLsession替代
或者使用第三方框架,AFNetworking,最好封装一下。
1.在开发的时候可以创建一个工具类,继承自我们的AFN中的请求管理者,再控制器中真正发请求的代码使用自己封装的工具类。
2.这样做的优点是以后如果修改了底层依赖的框架,那么我们修改这个工具类就可以了,而不用再一个一个的去修改。
3.该工具类一般提供一个单例方法,在该方法中会设置一个基本的请求路径。
4.该方法通常还会提供对GET或POST请求的封装。
5.在外面的时候通过该工具类来发送请求
6.单例方法:
(instancetype)shareNetworkTools
{
static XMGNetworkTools *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 注意: BaseURL中一定要以/结尾
instance = [[self alloc] initWithBaseURL:[NSURL URLWithString:@"http://120.25.226.186:32812/"]];
});
return instance;
}
-
如何处理多个网络请求并发的情况
- 使用GCD 信号量
- 使用NSOperation 添加依赖
-
在网络请求中如何提高性能
- 通过异步请求,开启子线程
-
在网络请求中如何保证安全性
- 尽量不要操作同一块内存,可以使用加锁的方式,AFNetworking是线程安全的做了处理
语言与基础知识:
1.内存中的栈和堆的区别是什么?那些数据在栈上,哪些在堆上?
1.栈区(stack):由编译器自动分配释放,存放函数的参数值,局部变量等值。其操作方式类似于数据结构中的栈。
2.堆区(heap):一般由程序员分配释放,若程序员不释放,则可能会引起内存泄漏。注堆和数据结构中的堆栈不一样,其类是与链表。
操作系统iOS 中应用程序使用的计算机内存不是统一分配空间,运行代码使用的空间在三个不同的内存区域,分成三个段:“text segment “,“stack segment ”,“heap segment ”。
2.#define和const定义的变量,有什么区别
define宏定义和const常变量区别:
1.define是宏定义,程序在预处理阶段将用define定义的内容进行了替换。因此程序运行时,常量表中并没有用define定义的常量,系统不为它分配内存。
const定义的常量,在程序运行时在常量表中,系统为它分配内存。
2.define定义的常量,预处理时只是直接进行了替换。所以编译时不能进行数据类型检验。
const定义的常量,在编译时进行严格的类型检验,可以避免出错。
3.define定义表达式时要注意“边缘效应”,例如如下定义:
#define N 2+3 //我们预想的N值是5,我们这样使用N
int a = N/2; //我们预想的a的值是2.5,可实际上a的值是3.5
3.什么情况下会出现内存的循环引用
(1)计时器NSTimer
一方面,NSTimer经常会被作为某个类的成员变量,而NSTimer初始化时要指定self为target,容易造成循环引用。 另一方面,若timer一直处于validate的状态,则其引用计数将始终大于0。记得释放
(2)block
block在copy时都会对block内部用到的对象进行强引用(ARC)或者retainCount增1(非ARC)。在ARC与非ARC环境下对block使用不当都会引起循环引用问题,
一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,简单说就是self.someBlock = ^(Type var){[self dosomething];或者self.otherVar = XXX;或者_otherVar = ...};
block的这种循环引用会被编译器捕捉到并及时提醒。
(3)委托delegate
在委托问题上出现循环引用问题已经是老生常谈了,本文也不再细讲,规避该问题的杀手锏也是简单到哭,一字诀:声明delegate时请用assign(MRC)或者weak(ARC),千万别手贱玩一下retain或者strong,毕竟这基本逃不掉循环引用了!
4.block中的weak self,是任何时候都需要加的么?
一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,简单说就是self.someBlock = ^(Type var){[self dosomething];或者self.otherVar = XXX;或者_otherVar = ...};
5.GCD的queue,main queue中执行的代码,一定是在main thread么?
不一定,如果queue是自己创建的那就在子线程,main queue中的一定是在main thread中的
6.NSOperationQueue有哪些使用方式
不知道
7.NSThread中的Runloop的作用,如何使用?
RunLoop是维持一个线程一直保持运转的,是线程的基本组成成分,RunLoop中至少有一种model model中又至少有事件源 timer事件, ob 其中的一个
8..h文件中的变量,外部可以直接访问么?(注意是变量,不是property)
不能,需要写变量的get方法 而属性已经直接给我们自动生成了
9.讲述一下runtime的概念,message send如果寻找不到相应的对象,会如何进行后续处理 ?
runtime是oc的运行时机制,其中最重要的是他的消息机制,
RunTime 运行机制 :运行时候的一些机制
>最重要的是消息机制
>方法调用的本质就是让对象发送消息 只有对象能够发送消息,所以使用objc_开头,就算是 类方法也是类对象在发送消息 :发送消息的过程是runtime库会根据isa指针找到对应的 类 在类和父类的方法列表中找 如果在最顶类(NSObject)中也没有找到的话,会报方 法找不到这个错 <oc 给了我们三个拯救的机会
(1)Method resolution :调用
+ (BOOL)resolveClassMethod:(SEL)sel
+ (BOOL)resolveInstanceMethod:(SEL)sel
(2) Fast forwarding
(3) Normal forwarding
>
>一些项目中能用的技术
(1)使用runtime交换方法:系统类 的方法功能不够;1使用继承类,重写方法 2使用runtime交换方法 :使用分类,只有分类才能给系统的类添加方法,并且通过添加的这个方法来进行方法交换,交换步骤在分类的load 方法中调用, 通过class_getClassMethod
获取方法地址, 通过 method_exchangeImplementations 交换方法注意的是 在方法交换后如果你在实现自己的方法的时候,要记住系统的方法已经被我们换掉了,所以调用我们自己的方法就代表调用系统的方法
(2)使用runtime动态添加方法:如果一个类方法非常多,加载类到内存的时候也比较消耗资源,可以使用runtime动态添加方法来解决 <经典面试题:有没有使用performSelector,其实主要想问你有没有动态添加过方法。> :
10.TCP和UDP的区别是什么?
TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。
UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快。
11.MD5和Base64的区别是什么,各自场景是什么?
md5 用户密码存储 文件校验
base64 公开的代码加密 url加密
12.二叉搜索树的概念,时间复杂度多少?
采用二叉树链表作为存储结构,每个左节点均小于父节点,每个右节点均大于父节点
O(log2(n))
架构:
哪些类不适合使用单例模式?即使他们在周期中只会出现一次。
Notification的使用场景是什么?同步还是异步?
简单介绍一下KVC和KVO,他们都可以应用在哪些场景?
- KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知
- KVC是KeyValueCoding的简称,它是一种可以直接通过字符串的名字(key)来访问类属性(实例变量)的机制。而不是通过调用Setter、Getter方法访问
APP相关:
如何添加一个自定义字体到工程中
如何制作一个静态库/动态库,他们的区别是什么?
Configuration中,debug和release的区别是什么?
简单介绍下发送系统消息的机制(APNS)
UI:
系统如何寻找到需要响应用户操作的那个Responder
逐层向上抛事件,如果到UIwindow都没有可以处理的报方法找不到异常
多屏幕尺寸的适配
要么使用xib的自动布局,autolayout或者使用屏幕宽度来设置margin也可以比较简单,还有种奇葩的是根据判断机器型号来的(⊙o⊙)
UIButton的父类是什么?UILabel呢?
UIController UIView
push view controller 和 present view controller的区别
描述下tableview cell的重用机制
Tableview会去缓存池中去取绑定标示的cell,(如果不清楚缓存机制,那么就会导致数据展示混乱),自定义不等高cell是常见的tableview处理手段,比较好的做法是在cell的model中重新定义一个height的变量,在setmodel的时候我们就应该吧需要的高度计算好,然后在tableview的rowHeight方法中取出model中的height设置,还有其他的方法,如果是在rowHeight方法中计算,这种方式不可用,会是的tableView卡顿
UIView的frame和bounds的区别是什么
Frame的0,0在父控件上,而bounds是在自身上
最后是几道场景题,也是我最喜欢问的:
发送10个网络请求,然后再接收到所有回应之后执行后续操作,如何实现?
实现一个第三方控件,可以在任何时候出现在APP界面最上层
实现一个最简单的点击拖拽功能。
上面那个拖拽之外,如果在手放开时,需要根据速度往前滑动呢?
如何减小一个应用程序的尺寸?
如何提高一个性用程序的性能?
不同版本的APP,数据库结构变化了,如何处理?
- revise by 简书.lovepeijun
- 题目来至知乎:来源地址
//本人自己添加的一些
Block 链式编程