物理内存虚拟内存的关系、堆栈、
比如工作环境,薪资待遇,要不要加班,主要工作内容,要用到什么技术,团队有没有什么缺点?
或者问你们打算用 swift 么?你们怎么看待函数式编程?我不会用 SB,你们要用么
1.进程的有哪几种状态
- 就绪-执行(进程调度)
- 执行-就绪(时间片到)
- 执行-阻塞(有事件请求)
- 阻塞-就绪(事件完成)
2.线程和进程的区别
进程有自己独立的地址空间,一个进程崩溃后,在保护模式下,他不会对其他进程造成影响。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,因此一个线程崩溃后就等于整个进程死掉了。
因此多进程的程序一般比多线程程序健壮,但是进程切换的时候,进程资源消耗要大些,效率低一些。
。
简而言之:
- 他们在执行过程中也是有区别的,每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够单独执行,必须依存在程序当中,由程序提供多线程的控制。
- 逻辑角度讲,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行,但是操作系统没有把多线程视为多个应用来进行进程的调度和管理及资源分配。<b>这是线程和进程的重要区别</b>
3.堆和栈的区别
- 堆空间的内存是动态分配的,一般存放对象,并且需要手动释放内存
- 栈空间的内存由系统自动分配,一般存放局部变量等,不需要手动管理内存
4.进程间通讯
- 消息传递
- 同步
- 共享内存区
- 进程调用
5.电路交换与分组交换有什么区别?
电路交换
优点:
- 传输时延小
- 实时性强
- 不会失序
缺点:
- 平均连接建立事件长
- 信道利用率低
分组交换
优点:
- 不存在连接建立时延
6.进程间通讯方式
- 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
- 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
- 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。不是用于交换大批数据,而用于多线程之间的同步.常作为一种锁机制,防止某进程在访问资源时其它进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
- 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
- 信号 ( signal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
- [共享内存( shared memory )] :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
- 套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
7.内存管理
连续内存分配(有内部碎片)
- 多分区方法:将内存分成许多个大小相同的模块,浪费巨大,不灵活(单位块大小不好决定),已弃用。
- 可变分区:操作系统有个表,用于记录哪些内存可用和哪些内存已经被占用。可用内存称为孔,进程进来过后,内存管理单元会自动找到合适的孔(注1),如果孔还有剩余,那么这个孔还是可用,只是内存变小了而已。
注1:策略有最先适应,最佳适应,最差适应。
非连续内存分配
分页:将物理内存分为大小固定的块,称为帧( frame),逻辑地址分为同样大小的块,称为页(page)
TLB缓存访问记录,他是个哈希表,key存的逻辑地址,value存的真正的物理内存。
24 OSI七层协议、TCP四层
物理层:一个(不一定可靠)点对点数据直链。
数据链路层:一个可靠的点对点数据直链。
网络层:在网络的各个节点之间进行地址分配、路由和分发报文。(IP协议)
传输层:在网络的各个节点之间可靠地分发数据包。(TCP协议)
会话层:主机间通讯,管理应用程序之间的会话。
表示层:数据表示形式,加密与解密。
应用层:网络进程到应用进程。(HTTP/Https、FTP、SMTP)
网络接口层
网络互连层
传输层
应用层
6.TCP/IP有哪几层
4层:(主流)
1.网络接口层 2.互联网层 3.传输层 4.应用层
5层:1.物理层 2.数据链路层 3.互联网从 4.传输层 5.应用层
Nullability
7.SDWebImage
1、缓存时间有多长:1周
_maxCacheAge = k
2、SDWebImage的内存缓存是用什么实现的?
NSCache
3、SDWebIamge的最大并发数是多少?
6
4、支持动图吗?
支持gif图
5、
<font color = 'red'>block更加面向结果,而代理更加面向过程。</font>
8.Delegate、Notification、KVO各自优缺点
他们的主要用途都是用来协调不同对象之间的消息同喜的。先说delegate吧,delegate只能一对一通信,通知和KVO可以一对多,但是他们只负责发送消息,没有返回参数。
delegate
当一个类的某些功能需要由别的类来实现,但是又不确定具体会是哪个类实现,即常用的delegate。委托模式iOS大量使用,委托可以很方便地做到接口和实现的分离,他的优势是解耦合
delegate的优点主要是它有非常严格的语法,它所有监听的事件在协议里都有清晰的声明:
- 协议可以直接多继承,而且一个对象可以定义多个不同的协议对象,每个协议对象可以有不同的代理实现
- 如果delegate中的require方法没有定义,编译器会发出警告,这也是它很不错的优点。
- 更重要的是它不会给架构的设计带来太大的困扰,它在一个应用的控制流程中是可追踪识别的
- 不需要第三方对象来保持或者监听通信过程。
缺点:
- 需要定义很多方法(协议本身定义、的delegate属性、delegate本身的实现)
- 释放代理对象时,需要小心的将delegate改为nil,一旦设定失败,那么调用释放对象
通知
一个对象通知另外一个对象,可以用来传递参数、通信等作用,与delegate的一对一不同,通知是一对多的。在一个对象中注册了通知,那么其他任意对象都可以来对这个对象发出通知。
NSNotificationCenter 是一个单例,是同步的。
NSNotificationQueue 是异步的,有三种:
typedef NS_ENUM(NSUInteger, NSPostingStyle) {
NSPostWhenIdle = 1, // 空闲时发送
NSPostASAP = 2, // 尽快发送
NSPostNow = 3 // 立即发送
};
他的优点是
- 比较简单,它不需要写多少代码,实现比较简单。一对多的实现也简单。
他也有一些缺点,
- 编译期不会检查通知是否能被观察者正确处理。而且调试的时候工作和控制过程不好跟踪,还有就是通知发出后不能从观察者获得反馈信息。
- 释放对象前一定要取消注册,否则这个通知再出现,会出现unrecognize instance错误,程序会崩溃。通知差不多就这些吧,其他的暂时想不起来了。
KVO
函数原型
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
}
简单来讲,KVO就是当其他对象的属性改变时会让自己收到通知(当然只能通过set来改变)。KVO很强大,但是API做得不是很好,Tompson也吐槽过这个,就是AF的作者
KVO 的优点很明显就是不需要发送通知,底层帮我们实现了自动响应,可以做binder,实现两个对象间的同步。
KVO 可以对属性值实现细粒度的观察,这一点是别的方法不容易做到的,也是很有用的一个特性。
缺点:
- 严重依赖于string,也就是说,编译器没办法在编译阶段将错误的keyPath给找出来,而且对属性重构过后,观察代码也得改。
- 所有的observe处理都放在一个方法里,如果KVO处理的事情种类多且繁杂,代码就很长很不雅观。
- 还有一点就是需要自己处理父类的observe事务,虽然很多时候runtime会自动帮忙处理父类的方法,比如对于dealloc,但是KVO不会,所以我们要在if语句的最后调用super的observeValueForKeyPath:函数。
- 多次removeObserver还会导致crash,一个文件还比较好debug,但是跨文件执行两次相同的removeObserver就不是那么容易发现了。
总的来说,KVO很强大,但也有点坑,使用它要养成好习惯。
9.MVVM与MVC
MVC
- Model: 表示业务数据对象
- View:展现数据的 UI
- Controller:Model 跟 View 之间的粘合剂。一方面对 View 上的行为作出反应,通常会涉及到 Model 的更改;另一方面将 Model 的改动反映到 View 上
MVC最大的优点就是他的概念简单,容易理解,几乎任何的程序员都会有所了解,它是最基础的设计模式,展现了一个架构抽象分离的精髓思想。在iOS客户端开发里面,MVC也是官方推荐的主流架构,是一种非常通用成熟的架构设计,但是MVC里面View Controller 承担的职责太多:
- 网络请求
- 数据访存
- UI调整
- View的delegate、datasource
- 业务逻辑
- 状态维护
与单一责任准则背道而驰。所以MVC也被很多人称为 Massive View Controller。
臃肿的View Controller使APP的维护成本非常高。所以MVVM和VIPER这些架构就出现了。
(还有个VIPER的)MVVM 相比 MVC 到底有哪些好处呢?我想,主要可以归纳为以下三点:
通常会把大量原来放在 ViewController 里的视图逻辑和数据逻辑移到 ViewModel 里,从而有效的减轻了 ViewController 的负担。另外通过分离出来的 ViewModel 获得了更好的测试性,我们可以针对 ViewModel 来测试,解决了界面元素难于测试的问题。MVVM 通常还会和一个强大的绑定机制一同工作,一旦 ViewModel 所对应的 Model 发生变化时,ViewModel 的属性也会发生变化,而相对应的 View 也随即产生变化。
MVVM的缺点:
- 不够直观,学习成本和开发成本都很高,MVVM提高了代码整体的复杂度,对新入职的员工有一定的学习成本,这种模式学习曲线很大不好掌握,对于新项目来说可以使用,但是对于一个已经很复杂的大中型项目,就不太好动框架这层东西了。
- 苹果也没有现成的绑定机制,要发挥MVVM的优势要么用KVO,要么引入ReactiveCocoa这样的第三方库,会增加学习成本和开发成本进一步增高。
- 另一个缺点是数据绑定使得Debug变得更难了,数据绑定使程序异常能快速的传递到其他位置,比如在界面上发现的bug可能是viewModel造成的,也有可能是model造成的,数据链越长,对bug定位越困难。
- 在传统的MVVM中,ViewModel依然要承载大量的逻辑,包括业务逻辑,界面逻辑,数据访存和网络相关,使得ViewModel仍然有可能变得和MVC一样臃肿。
基于MVC模式的变形,SOA面向服务,比如Glow公司,(这是一个上海的公司,里面有很多硅谷的大牛),他们的变形就是、应用层、服务层和数据层
Paste_Image.png1、 非容器对象对不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝)。对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。
2、
容器对象
对于容器本身,同非容器对象
。
但是,对于容器内的对象,则都是指针复制。真正的深拷贝(即容器本身、容器内的对象均为深拷贝),实现方式如下:
NSArray
*trueDeepCopyArray =
[
NSKeyedUnarchiver
unarchiveObjectWithData
:[
NSKeyedArchiver
archivedDataWithRootObject
:originArray]];
originArray-
待拷贝数组
32.自己在编写程序的时候,遇到BUG是如何解决的?用了哪些解决方法?
- 有效的Log;Log一些重要的事件
- 全局断点:
- 条件断点:
- 控制台进行手动打印:po
- 跟踪对象的生命周期;跟踪数据传递的过程
- 分析层级结构
- Enable NSZombie Objects(开启僵尸对象):开启僵尸对象,首先打开“Edit Scheme”,然后选择Diagnostics选项卡,勾选Enable NSZombie Objects选项。
- 静态分析(Analyze内存泄漏分析)和动态分析()
http://blog.csdn.net/totogo2010/article/details/8233565
33.Runtime
一条消息也就 objc_msgSend 做了什么事。举 objc_msgSend(obj, foo) 这个例子来说:
首先,通过 obj 的 isa 指针找到它的 class ;
在 class 的 method list 找 foo ;
如果 class 中没到 foo,继续往它的 superclass 中找 ;
一旦找到 foo 这个函数,就去执行它的实现IMP .
但这种实现有个问题,效率低。但一个 class 往往只有 20% 的函数会被经常调用,可能占总调用次数的 80% 。每个消息都需要遍历一次 objc_method_list 并不合理。如果把经常被调用的函数缓存下来,那可以大大提高函数查询的效率。这也就是 objc_class 中另一个重要成员 objc_cache 做的事情 - 再找到 foo 之后,把 foo 的 method_name 作为 key ,method_imp 作为 value 给存起来。当再次收到 foo 消息的时候,可以直接在 cache 里找到,避免去遍历 objc_method_list.
一个OBJC对象如何进行内存布局?(考虑有父类的情况)
- 所有父类的成员变量和自己的成员变量都会存放在该对象所对应的存储空间中
- 父类的方法和自己的方法都会缓存在类对象的方法缓存中,类方法是缓存在元类对象中
- 每一个对象内部都有一个isa指针,指向他的类对象,类对象中存放着本对象的如下信息:
- 对象方法列表
- 成员变量列表
- 属性列表
你在项目中遇到的难点?
熟悉 CocoaPods 么?能大概讲一下工作原理么?
CocoaPods原理:
1.Pods项目最终会编译成一个名为libPods.a的文件,主项目只需要依赖这个.a文件即可
2.对于资源文件,CocoaPods提供了一个名为Pods-resources.sh的bash脚本,该脚本在每次项目编译的时候都会执行,将第三方的各种资源文件复制到目标目录中
3.CocoaPods通过一个名为Pods.xcconfig的文件在编译时设置所有的依赖和参数
UIScrollView 大概是如何实现的,它是如何捕捉、响应手势的?
- 我对UIScrollView的理解是frame就是他的contentSize,bounds就是他的可视范围,通过改变bounds从而达到让用户误以为在滚动,以下是一个简单的UIScrollView实现
- 第二个问题个人理解是解决手势冲突,对自己添加的手势进行捕获和响应
UIView 和 CALayer 之间的关系?
- UIView显示在屏幕上归功于CALayer,通过调用drawRect方法来渲染自身的内容,调节CALayer属性可以调整UIView的外观,UIView继承自UIResponder,CALayer不可以响应用户事件
- UIView是iOS系统中界面元素的基础,所有的界面元素都继承自它。它内部是由Core Animation来实现的,它真正的绘图部分,是由一个叫CALayer(Core Animation Layer)的类来管理。UIView本身,更像是一个CALayer的管理器,访问它的根绘图和坐标有关的属性,如frame,bounds等,实际上内部都是访问它所在CALayer的相关属性
- UIView有个layer属性,可以返回它的主CALayer实例,UIView有一个layerClass方法,返回主layer所使用的类,UIView的子类,可以通过重载这个方法,来让UIView使用不同的CALayer来显示
如果我这次失败的,今年还有没有另外的机会加入xx”,结果面试官说“你为什么觉得自己会失败呢,你对自己没有信心吗?”,我说“不是这样的,只是我非常想加入百度而已”
网友评论