1、什么是KVO和KVC
KVO是观察者,它提供了观察某一属性变化的方法,极大的简化了代码。对于系统是根据keyPath去取到相应的值发生改变,理论上来讲和KVC的机制道理一样。
KVC是键值编码是一种间接访问对象的属性使用字符串来标识属性,而不是通过调用存取方法,直接或间接通过实例变量访问的机制
2、Apple Pay是什么?它的大概工作流程是怎样的?
是苹果研制的一款用于支付的应用。
ApplePay依靠NFC芯片,通过结合Touch ID,可以便捷完成移动端支付,并且可以通过拍照添加信用卡。Apple
Pay所有存储的支付信息都是经过加密的,用户可以通过Find my iPhone来关闭所有的支付功能。此外,iTunes用户可以使用iTunes中已经存储的信用卡信息。
ApplePay在消费支付流程里是扮演的是支付通道的角色,把实物信用卡电子化。通过Apple
Pay消费的时候,信用卡消费信息是通过苹果的通道到银联,银联再跟相关的发卡商结算。
3、如何应对APP版本升级,数据结构随之变化?
如果是移动端,
视数据的重要性来定, 如果不重要, 那就忽视它. 如果重要,
就要额外做一个检查Documents(我这里假设你的数据文件放在Documents下)下的数据文件, 如果存在,
就SQL导出再加上按照新的数据结构导入到新的数据文件. 也就是两句SQL的事, 在升级后第一次进入应用的时候做这个事.
如果是服务端,
正常情况还是需要做接口层(当然, 我也遇到没做接口层, 直接远程数据库操作的, 对这种, 我无话可说), 接口层的变动幅度, 往往没有数据层的变动大,
有时候, 哪怕数据结构变化了, 但接口层还是一样. 如果是碰到数据层变化逼迫接口层变化的情况, 那就需要保留老接口的同时, 提供新接口服务,
直到使用老接口的app保有量低到一定程度, 再关闭老接口. 我的产品接口, 是在接口中加上一个v(version)参数作为版本判断标志.
4、常用的设计模式
(一)代理模式
应用场景:当一个类的某些功能需要由别的类来实现,但是又不确定具体会是哪个类实现。
优势:解耦合
敏捷原则:开放-封闭原则
实例:tableview的
数据源delegate,通过和protocol的配合,完成委托诉求。
列表row个数delegate
自定义的delegate
(二)观察者模式
应用场景:一般为model层对,controller和view进行的通知方式,不关心谁去接收,只负责发布信息。
优势:解耦合
敏捷原则:接口隔离原则,开放-封闭原则
实例:Notification通知中心,注册通知中心,任何位置可以发送消息,注册观察者的对象可以接收。
kvo,键值对改变通知的观察者,平时基本没用过。
(三)MVC模式
应用场景:是一中非常古老的设计模式,通过数据模型,控制器逻辑,视图展示将应用程序进行逻辑划分。
优势:使系统,层次清晰,职责分明,易于维护
敏捷原则:对扩展开放-对修改封闭
实例:model-即数据模型,view-视图展示,controller进行UI展现和数据交互的逻辑控制。
(四)单例模式
应用场景:确保程序运行期某个类,只有一份实例,用于进行资源共享控制。
优势:使用简单,延时求值,易于跨模块
敏捷原则:单一职责原则
实例:[UIApplication sharedApplication]。
注意事项:确保使用者只能通过
getInstance方法才能获得,单例类的唯一实例。
java,C++中使其没有公有构造函数,私有化并覆盖其构造函数。
objectc中,重写allocWithZone方法,保证即使用户用 alloc方法直接创建单例类的实例,
返回的也只是此单例类的唯一静态变量。
(五)策略模式
应用场景:定义算法族,封装起来,使他们之间可以相互替换。
优势:使算法的变化独立于使用算法的用户
敏捷原则:接口隔离原则;多用组合,少用继承;针对接口编程,而非实现。
实例:排序算法,NSArray的sortedArrayUsingSelector;经典的鸭子会叫,会飞案例。
注意事项:1,剥离类中易于变化的行为,通过组合的方式嵌入抽象基类
2,变化的行为抽象基类为,所有可变变化的父类
3,用户类的最终实例,通过注入行为实例的方式,设定易变行为
防止了继承行为方式,导致无关行为污染子类。完成了策略封装和可替换性。
(六)工厂模式
应用场景:工厂方式创建类的实例,多与proxy模式配合,创建可替换代理类。
优势:易于替换,面向抽象编程,application只与抽象工厂和易变类的共性抽象类发生调用关系。
敏捷原则:DIP依赖倒置原则
实例:项目部署环境中依赖多个不同类型的数据库时,需要使用工厂配合proxy完成易用性替换
注意事项:项目初期,软件结构和需求都没有稳定下来时,不建议使用此模式,因为其劣势也很明显,
增加了代码的复杂度,增加了调用层次,增加了内存负担。所以要注意防止模式的滥用。
5、单例会有什么弊端?
主要优点:
1、提供了对唯一实例的受控访问。
2、由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能。
3、允许可变数目的实例。
主要缺点:
1、由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
2、单例类的职责过重,在一定程度上违背了“单一职责原则”。
3、滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。
6、你会如何存储用户的一些敏感信息,如登录的token
使用keychain来存储,也就是钥匙串,使用keychain需要导入Security框架
iOS的keychain服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个ios程序都有一个独立的keychain存储。相对于
NSUserDefaults、文件保存等一般方式,keychain保存更为安全,而且keychain里保存的信息不会因App被删除而丢失,所以在
重装App后,keychain里的数据还能使用。从ios 3。0开始,跨程序分享keychain变得可行。
7、什么时候会使用CoreGraphics,以及使用步骤?
CoreGraphics是基于C的API,当使用绘图操作的时候才能用到!
获取上下文(画布)
创建路径(自定义或者调用系统的API)并添加到上下文中。
进行绘图内容的设置(画笔颜色、粗细、填充区域颜色、阴影、连接点形状等)
开始绘图(CGContextDrawPath)
释放路径(CGPathRelease)
8、block底层实现
block本质是指向一个结构体的一个指针
运行时机制 比较高级的特性 纯C语言
平时写的OC代码 转换成C语言运行时的代码
指令:clang -rewrite-objc main.m(可以打印验证)
默认情况下,任何block都是在栈里面的,随时可能被回收
只要对其做一次copy操作
block的内存就会放在堆里面 不会释放
只有copy才能产生一个新的内存地址 所有地址会发生改变
9、UIScrollView大概是如何实现的,它是如何捕捉、响应手势的?
UIScrollView在滚动过程当中,其实是在修改原点坐标。当手指触摸后,scroll view会暂时拦截触摸事件,使用一个计时器。假如在计时器到点后没有发生手指移动事件,那么 scroll view 发送 trackingevents 到被点击的 subview。假如在计时器到点前发生了移动事件,那么 scroll view 取消 tracking 自己发生滚动。
首先了解下UIScrollView对于touch事件的接收处理原理:
UIScrollView应该是重载了hitTest方法,并总会返回itself 。所以所有的touch事件都会进入到它自己里面去了。内部的touch事件检测到这个事件是不是和自己相关的,或者处理或者除递给内部的view。
为了检测touch是处理还是传递,UIScrollView当touch发生时会生成一个timer。
1,如果150ms内touch未产生移动,它就把这个事件传递给内部view
2,如果150ms内touch产生移动,开始scrolling,不会传递给内部的view。(例如,当你touch一个table时候,直接scrolling,你touch的那行永远不会highlight。)
3,如果150ms内touch未产生移动并且UIScrollView开始传递内部的view事件,但是移动足够远的话,且canCancelContentTouches
= YES,UIScrollView会调用touchesCancelled方法,cancel掉内部view的事件响应,并开始scrolling。(例如,当你touch一个table, 停止了一会,然后开始scrolling,那一行就首先被highlight,但是随后就不在高亮了)
10、NSOperation相比于GCD 有哪些优势?
GCD是基于c的底层api,NSOperation属于object-c类。ios 首先引入的是NSOperation,IOS4之后引入了GCD和NSOperationQueue并且其内部是用gcd实现的。
相对于GCD:
1,NSOperation拥有更多的函数可用,具体查看api。
2,在NSOperationQueue中,可以建立各个NSOperation之间的依赖关系。
3,有kvo,可以监测operation是否正在执行(isExecuted)、是否结束(isFinished),是否取消(isCanceld)。
4,NSOperationQueue可以方便的管理并发、NSOperation之间的优先级。
GCD主要与block结合使用。代码简洁高效。
GCD也可以实现复杂的多线程应用,主要是建立个个线程时间的依赖关系这类的情况,但是需要自己实现相比NSOperation要复杂。
具体使用哪个,依需求而定。 从个人使用的感觉来看,比较合适的用法是:除了依赖关系尽量使用GCD,因为苹果专门为GCD做了性能上面的优化。
11、如何实现夜间模式?
1.准备两套资源,分别对应日间模式和夜间模式。
2.在系统全局保存一个变量(BOOL isNight),根据用户的操作改变这个变量的值;
3.把每个需要被改变的view,viewcontroller加入通知中心中监听(NeedTransferToNight和NeedTransferToDay)事件;
4.默认为日间模式,isNight= YES.
5.当用户点击夜间按钮时,如果isNight == YES,讲此变量的值置为NO,通知中心发布NeedTransferToNight通知,所有需要被改变的view和viewcontroller在监听到此事件时使用夜间资源重新绘制自身。其他view在初始化时如果发现isNight为YES.则使用夜间资源初始化自身。(反之亦然)
6.运行程序,可以看到夜间模式。
12、frame 与 center bounds的关系
1.frame属性是相对于父容器的定位坐标。
2.bounds属性针对于自己,指明大小边框,默认点为(0,0),而宽和高与frame宽和高相等。
3.center属性是针对与frame属性的中心点坐标。
4.当frame变化时,bounds和center相应变化。
5.当bounds变化时,frame会根据新bounds的宽和高,在不改变center的情况下,进行重新设定。
6, center永远与frame相关,指定frame的中心坐标!
13、断点续传如何实现的?
断点续传的理解可以分为两部分:一部分是断点,一部分是续传。断点的由来是在下载过程中,将一个下载文件分成了多个部分,同时进行多个部分一起的下载,当某个时间点,任务被暂停了,此时下载暂停的位置就是断点了。续传就是当一个未完成的下载任务再次开始时,会从上次的断点继续传送。
使用多线程断点续传下载的时候,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,多个线程并发可以占用服务器端更多资源,从而加快下载速度。
在下载(或上传)过程中,如果网络故障、电量不足等原因导致下载中断,这就需要使用到断点续传功能。下次启动时,可以从记录位置(已经下载的部分)开始,继续下载以后未下载的部分,避免重复部分的下载。断点续传实质就是能记录上一次已下载完成的位置。
断点续传的过程
①断点续传需要在下载过程中记录每条线程的下载进度;
②每次下载开始之前先读取数据库,查询是否有未完成的记录,有就继续下载,没有则创建新记录插入数据库;
③在每次向文件中写入数据之后,在数据库中更新下载进度;
④下载完成之后删除数据库中下载记录。
14、push Notification原理
本地推送:不需要联网也可以推送,是开发人员在APP内设定特定的时间来提醒用户干什么
远程推送:需要联网,用户的设备会于苹果APNS服务器形成一个长连接,用户设备会发送uuid和Bundle idenidentifier给苹果服务器,苹果服务器会加密生成一个deviceToken给用户设备,然后设备会将deviceToken发送给APP的服务器,服务器会将deviceToken存进他们的数据库,这时候如果有人发送消息给我,服务器端就会去查询我的deviceToken,然后将deviceToken和要发送的信息发送给苹果服务器,苹果服务器通过deviceToken找到我的设备并将消息推送到我的设备上,这里还有个情况是如果APP在线,那么APP服务器会于APP产生一个长连接,这时候APPF服务器会直接通过deviceToken将消息推送到设备上