所有的面试题出自群主大神的笔记📒,摘抄整理,留着自己面试用。
KVO Delegation NSNotification
通知
通知比较灵活,不需要编写多少代码,实现比较简单;
对于一个发出的通知,多个对象能够做出反应,即1对多的方式
代理
代理的语法比较严格,如果delegate中的一个方法没有实现那么就会出现编译警告
需要定义很多代码
KVO
KVO性能不好(底层会动态产生新的类),只能监听某个对象属性的改变
KVO内部实现原理
KVO是基于runtime机制实现的
当某个类的对象第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类
中任何被观察属性的setter 方法。
派生类在被重写的setter 方法实现真正的通知机制(Person NSKVONotifying_Person)
我们说的oc是动态运行时语言是什么意思?
答:多态。主要是将数据类型的确定由编译时,推迟到了运行时。
这个问题其实浅涉及到两个概念,运行时和多态。
简单来说,运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。
多态:不同对象以自己的方式响应相同的消息的能力叫做多态。意思就是假设生物类(life)都用有一个相同的方法-eat;
那人类属于生物,猪也属于生物,都继承了life后,实现各自的eat,但是调用是我们只需调用各自的eat方法。
也就是不同的对象以自己的方式响应了相同的消息(响应了eat这个选择器)。
因此也可以说,运行时机制是多态的基础?~~~
什么是推送消息?
答:推送通知更是一种技术。
简单点就是客户端获取资源的一种手段。
普通情况下,都是客户端主动的pull。
推送则是服务器端主动push.
什么是谓词?
答:谓词是通过NSPredicate,是通过给定的逻辑条件作为约束条件,完成对数据的筛选。
predicate =
[NSPredicate predicateWithFormat:@"customerID
== %d",n];
a = [customers
filteredArrayUsingPredicate:predicate];
```
***
多线程是什么
```swift
答: 多线程是个复杂的概念,按字面意思是同步完成多项任务,提高了资源的使用效率,从硬件、操作系统、
应用软件不同的角度去看,多线程被赋予不同的内涵,对于硬件,现在市面上多数的CPU都是多核的,
多核的CPU运算多线程更为出色;从操作系统角度,是多任务,现在用的主流操作系统都是多任务的,
可以一边听歌、一边写博客;对于应用来说,多线程可以让应用有更快的回应,可以在网络下载时,
同时响应用户的触摸操作。在iOS应用中,对多线程最初的理解,就是并发,它的含义是原来先做烧水,
再摘菜,再炒菜的工作,会变成烧水的同时去摘菜,最后去炒菜。
iOS 中的多线程
答: iOS中的多线程,是Cocoa框架下的多线程,通过Cocoa的封装,可以让我们更为方便的使用线程,
做过C++的同学可能会对线程有更多的理解,比如线程的创立,信号量、共享变量有认识,Cocoa框架
下会方便很多,它对线程做了封装,有些封装,可以让我们创建的对象,本身便拥有线程,也就是线程
的对象化抽象,从而减少我们的工程,提供程序的健壮性。
GCD是(Grand
Central Dispatch)的缩写,从系统级别提供的一个易用地多线程类库,具有运行时的特点,
能充分利用多核心硬件。GCD的API接口为C语言的函数,函数参数中多数有Block
NSOperation与Queue
NSOperation是一个抽象类,它封装了线程的细节实现,我们可以通过子类化该对象,
加上NSQueue来同面向对象的思维,管理多线程程序。具体可参看这里:一个基于
NSOperation的多线程网络访问的项目。
NSThread
NSThread是一个控制线程执行的对象,它不如NSOperation抽象,通过它我们可以方便的得到
一个线程,并控制它。但NSThread的线程之间的并发控制,是需要我们自己来控制的,可以
通过NSCondition实现。
在项目什么时候选择使用GCD,什么时候选择NSOperation?
答: 项目中使用NSOperation的优点是NSOperation是对线程的高度抽象,在项目中使用它,会使项目的程序结构更好,子类化NSOperation的设计思路,是具有面向对象的优点(复用、封装),使得实现是多线程支持,而接口简单,建议在复杂项目中使用。
项目中使用GCD的优点是GCD本身非常简单、易用,对于不复杂的多线程操作,会节省代码量,而Block参数的使用,会是代码更为易读,建议在简单项目中使用。
谈谈Object-C的内存管理方式及过程?
答:
1)当你使用new,alloc和copy方法创建一个对象时,该对象的保留计数器值为1.当你不再使用该对象时,你要负责向该对象发送一条release或autorelease消息.这样,该对象将在使用寿命结束时被销毁.
2).当你通过任何其他方法获得一个对象时,则假设该对象的保留计数器值为1,而且已经被设置为自动释放,你不需要执行任何操作来确保该对象被清理.如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它.
3).如果你保留了某个对象,你需要(最终)释放或自动释放该对象.必须保持retain方法和release方法的使用次数相等.
Objective-C堆和栈的区别?
答:
管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。
申请大小:
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。
自动释放池是什么,如何工作
答:当您向一个对象发送一个autorelease消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放.它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。
http和scoket通信的区别。
答:http是客户端用http协议进行请求,发送请求时候需要封装http请求头,并绑定请求的数据,服务器一般有web服务器配合(当然也非绝对)。http请求方式为客户端主动发起请求,服务器才能给响应,一次请求完毕后则断开连接,以节省资源。服务器不能主动给客户端响应(除非采取http长连接技术)。iphone主要使用类是NSUrlConnection。
scoket是客户端跟服务器直接使用socket“套接字”进行连接,并没有规定连接后断开,所以客户端和服务器可以保持连接通道,双方都可以主动发送数据。一般在游戏开发或股票开发这种要求即时性很强并且保持发送数据量比较大的场合使用。主要使用类是CFSocketRef。
简述视图控件器的生命周期。
答:loadView 尽管不直接调用该方法,如多手动创建自己的视图,那么应该覆盖这个方法并将它们赋值给试图控制器的view 属性。
viewDidLoad
只有在视图控制器将其视图载入到内存之后才调用该方法,这是执行任何其他初始化操作的入口。
viewDidUnload
当试图控制器从内存释放自己的方法的时候调用,用于清除那些可能已经在试图控制器中创建的对象。
viewVillAppear
当试图将要添加到窗口中并且还不可见的时候或者上层视图移出图层后本视图变成顶级视图时调用该方法,用于执行诸如改变视图方向等的操作。实现该方法时确保调用[superview WillAppear: ]
viewDidAppear
当视图添加到窗口中以后或者上层视图移出图层后本视图变成顶级视图时调用,用于放置那些需要在视图显示后执行的代码。确保调用[superviewDidAppear:] 。
UIView与CLayer有什么区别?
答:
1).UIView
是 iOS 系统中界面元素的基础,所有的界面元素都是继承自它。它本身完全是由CoreAnimation 来实现的。它真正的绘图部分,是由一个CALayer 类来管理。UIView 本身更像是一个CALayer 的管理器,访问它的跟绘图和跟坐标有关的属性。
2).UIView
有个重要属性layer ,可以返回它的主CALayer 实例。
3).UIView的 CALayer 类似UIView 的子View 树形结构,也可以向它的layer 上添加子layer ,来完成某些特殊的表示。即CALayer 层是可以嵌套的。
4).UIView
的 layer 树形在系统内部,被维护着三份copy 。分别是逻辑树,这里是代码可以操纵的;动画树,是一个中间层,系统就在这一层上更改属性,进行各种渲染操作;显示树,其内容就是当前正被显示在屏幕上得内容。
5).动画的运作:对
UIView 的subLayer (非主Layer )属性进行更改,系统将自动进行动画生成,动画持续时间的缺省值似乎是0.5 秒。
6).坐标系统:
CALayer 的坐标系统比UIView 多了一个anchorPoint 属性,使用CGPoint 结构表示,值域是0~1 ,是个比例值。这个点是各种图形变换的坐标原点,同时会更改layer 的position 的位置,它的缺省值是{0.5,0.5} ,即在layer 的中央。
7).渲染:当更新层,改变不能立即显示在屏幕上。当所有的层都准备好时,可以调用setNeedsDisplay 方法来重绘显示。
8).变换:要在一个层中添加一个 3D 或仿射变换,可以分别设置层的transform 或affineTransform 属性。
9).变形:
Quartz Core 的渲染能力,使二维图像可以被自由操纵,就好像是三维的。图像可以在一个三维坐标系中以任意角度被旋转,缩放和倾斜。CATransform3D 的一套方法提供了一些魔术般的变换效果。
Quatrz 2D的绘图功能的三个核心概念是什么并简述其作用。
答:上下文:主要用于描述图形写入哪里;
路径:是在图层上绘制的内容;
状态:用于保存配置变换的值、填充和轮廓,alpha 值等。
CFSocket使用有哪几个步骤。
答:创建Socket 的上下文;创建Socket ;配置要访问的服务器信息;封装服务器信息;连接服务器;
ios 平台怎么做数据的持久化?coredata 和sqlite有无必然联系?coredata是一个关系型数据库吗?
答:iOS 中可以有四种持久化数据的方式:属性列表(plist)、对象归档、SQLite3 和Core Data;core data 可以使你以图形界面的方式快速的定义app 的数据模型,同时在你的代码中容易获取到它。coredata 提供了基础结构去处理常用的功能,例如保存,恢复,撤销和重做,允许你在app 中继续创建新的任务。在使用core data 的时候,你不用安装额外的数据库系统,因为core data 使用内置的sqlite 数据库。core data 将你app 的模型层放入到一组定义在内存中的数据对象。coredata 会追踪这些对象的改变,同时可以根据需要做相反的改变,例如用户执行撤销命令。当core data 在对你app 数据的改变进行保存的时候,core data 会把这些数据归档,并永久性保存。mac os x 中sqlite 库,它是一个轻量级功能强大的关系数据引擎,也很容易嵌入到应用程序。可以在多个平台使用,sqlite 是一个轻量级的嵌入式sql 数据库编程。与core data 框架不同的是,sqlite 是使用程序式的,sql 的主要的API 来直接操作数据表。Core Data 不是一个关系型数据库,也不是关系型数据库管理系统(RDBMS) 。虽然Core Dta 支持SQLite 作为一种存储类型,但它不能使用任意的SQLite 数据库。Core Data 在使用的过程种自己创建这个数据库。Core Data 支持对一、对多的关系。
tableView 的重用机制?
答:UITableView 通过重用单元格来达到节省内存的目的: 通过为每个单元格指定一个重用标识符(reuseIdentifier),即指定了单元格的种类,以及当单元格滚出屏幕时,允许恢复单元格以便重用.对于不同种类的单元格使用不同的ID,对于简单的表格,一个标识符就够了.
描述下SDWebImage里面给UIImageView加载图片的逻辑
• SDWebImage 中为 UIImageView 提供了一个分类UIImageView+WebCache.h, 这个分类中有一个最常用的接口sd_setImageWithURL:placeholderImage:,会在真实图片出现前会先显示占位图片,当真实图片被加载出来后在替换占位图片
• 加载图片的过程大致如下:
○ 首先会在 SDWebImageCache 中寻找图片是否有对应的缓存, 它会以url 作为数据的索引先在内存中寻找是否有对应的缓存
○ 如果缓存未找到就会利用通过MD5处理过的key来继续在磁盘中查询对应的数据, 如果找到了, 就会把磁盘中的数据加载到内存中,并将图片显示出来
○ 如果在内存和磁盘缓存中都没有找到,就会向远程服务器发送请求,开始下载图片
○ 下载后的图片会加入缓存中,并写入磁盘中
○ 整个获取图片的过程都是在子线程中执行,获取到图片后回到主线程将图片显示出来
设计个简单的图片内存缓存器
• 类似上面SDWebImage实现原理即可
• 一定要有移除策略:释放数据模型对象