面试题
1、有些图片加载的比较慢怎么处理?怎么优化性能?
图片下载放在异步线程
图片下载过程中使用占位图片
如果图片较大,可以考虑多线程断点下载
2、单例是怎么实现的
说白了就是一个类不通过alloc方式创建对象,而是用一个静态方法返回这个类的对象。系统只需要拥有一个的 全局对象,这样有利于我们协调系统整体的行为;
具体代码怎么写:dispath_once
怎么保障变量到这只执行一次:dispath_once
只保存一份内存地址:用static修饰变量
static的作用:全局的变量只初始化一次,把变量保存在静态分区中,程序从开始运行到结束变量只有一份内存地址
3、代理
自己用的不多,UITableView、UICollectionView这里都用到。把某个对象要做的事情委托给别的对象去做。那么别的对象就是这个对象的代理,代替它来打理要做的事。反映到程序中,首先要明确一个对象的委托方是哪个对象,委托所做的内容是什么。常见的如QQ的自动回复就属于代 理拦截,代理模式在iphone中得到广泛应用。
4、用的架构是什么模式?MVC三者之间是怎样相互通信的,V和C通过什么传递?
MVC是一种架构模式,M表示MOdel,V表示视图View,C表示控制器Controller,Model负责存储、定义、操作数据,View用来展示书给用户,和用户进行操作交互,Controller是Model和View的协调者,Controller把Model中的数据拿过来给View用。Controller可以直接与Model和View进行通信,而View不能和Controller直接通信。View与Controller通信需要利用代理协议的方式,Controller遵守代理,实现代理的方法,来监听View的事件。当有数据更新时,Model也要与Controller进行通信,这个时候就要用Notification和KVO,这个方式就像一个广播一样,Model发信号,Controller设置监听接受信号,当有数据更新时就发信号给Controller,Model和View不能直接进行通信,这样会违背MVC设计模式。
5、对观察者模式的理解
Notification 是观察者模式的实现,KVO是观察者模式的OB-C底层实现。
NOtification 通过 Notifydcation addobserver 和 remove observer 工作。当一个物体发生变化时,会通知所有观察这个物体的观察者让其做出反应。实现起来无非就是把所有观察者的 对象给这个物体,当这个物体的发生改变,就会调用遍历所有观察者的对象调用观察者的方法从而达到通知观察者的目的。
KVO(Key-Value- Observing) 是键值监听,键值观察机制,提供了观察某一属性变化的方法,底层实现:当观察者为一个对象的属性进行了注册,被观察对象的isa指针被修改的时候,isa指针就会指向一个中间类,而不是真实的类。所以 isa指针其实不需要指向实例对象真实的类。所以我们的程序最好不要依赖于isa指针。在调用类的方法的时候,最好要明确对象实例的类名
KVC(Key-Value-Coding)内部的实现:KVC是键值编码,是一种间接访问对象的属性,使用字符串来标示属性(例如:setValue:forKey:) ,一个对象在调setValue的时候,(1)首先根据方法名找到运行方法的时候所需要的环境参数。(2)他会从 isa指针结合环境参数,找到具体的方法实现的接口。(3)再直接查找得来的具体的方法实现。
6、代理和通知的区别
通知是一对多,代理是一对一
1、效率肯定是delegate比NSNotification高。
2、delegate方法比notification更加直接,需要关注返回值,所以delegate方法往往包含should这个很传神的词。相反的,notification最大的特色就是不关心结果。所以notification往往用did这个词汇。
3、两个模块之间联系不是很紧密,就用notification传值,例如多线程之间传值用notificaiton。
4、delegate只是一种较为简单的回调,且主要用在一个模块中,例如底层功能完成了,需要把一些值传到上层去,就事先把上层的函数通过delegate传到底层,然后在底层call这个delegate,它们都在一个模块中,完成一个功能,例如说 NavgationController 从 B 界面到A 点返回按钮 (调用popViewController方法) 可以用delegate比较好。
7、第三方框架 MapKit
MapKit苹果原生框架
8、微信支付和支付宝支付的区别
9、多线程NSOperation GCD区别
项目中使用NSOperation的优点是NSOperation是对线程的高度抽象,在项目中使用它,会使项目的程序结构更好,子类化NSOperation的设计思路,是具有面向对象的优点(复用、封装),使得实现是多线程支持,而接口简单,建议在复杂项目中使用。项目中使用GCD的优点是GCD本身非常简单、易用,对于不复杂的多线程操作,会节省代码量,而Block参数的使用,会是代码更为易读,建议在简单项目中使用。
10、block,block在哪种情况下会造成循环引用,如何解决?
(1) block本质是一个数据类型,多用于参数传递,代替代理方法, (有多个参数需要传递或者多个代理方法需要实现还是推荐使用代理方法),少用于当做返回值传递. block是一个OC对象,它的功能是保存代码片段,预先准备好代码,并在需要的时候执行.
(2)因为使用block代码块可能会引起内部循坏引用,所以应在block定义前加上修饰
(1)从两方面分析造成循环引用问题
当self拥有一个block的时候,在block又调用self的方法(或者self所拥有的某个属性)。形成你中有我,我中有你,这种时候会造成循环引用 (你拥有一个对象包含了另外了一个实例变量对象,但是第二个对象又把前一个对象作为它的委托,那么这两个对象将不会被释放。)
把某个实例变量变成本地临时变量,强引用将直接指向这个本地临时变量,但本地临时变量一般都会很快释放,所以一般考虑第一种情况
(2)解决方案:对block进行修饰__weak(arc)或__block(mrc)
11、属性修饰符copy、strong区别
OC中NSString为不可变字符串的时候,用copy和strong都是只分配一次内存,但是如果用copy的时候,需要先判断字符串是否不可变字符串,如果是不可变字符串,就不再分配空间,如果是可变字符串才分配空间。如果程序中用到NSString的地方特别的,每一次都要先进行判断就会消耗性能,影响用户体验,用strong就不会再进行判断,所以,不可变字符串可以直接用strong。
属性修饰符weak、strong区别
weak :弱引用 ,ARC中使用,如果只想的对象被释放了,其指向nil,可以有效的避免野指针,其引用计数为1。
strong :强引用,ARC中使用,与MRC中retain类似,使用之后,计数器+1。
(weak和strong)不同的是 当一个对象不再有strong类型的指针指向它的时候 它会被释放 ,即使还有weak型指针指向它。
一旦最后一个strong型指针离去 ,这个对象将被释放,所有剩余的weak型指针都将被清除。
可能有个例子形容是妥当的。
想象我们的对象是一条狗,狗想要跑掉(被释放)。
strong型指针就像是栓住的狗。只要你用牵绳挂住狗,狗就不会跑掉。如果有5个人牵着一条狗(5个strong型指针指向1个对象),除非5个牵绳都脱落 ,否着狗是不会跑掉的。
weak型指针就像是一个小孩指着狗喊到:“看!一只狗在那” 只要狗一直被栓着,小孩就能看到狗,(weak指针)会一直指向它。只要狗的牵绳脱落,狗就会跑掉,不管有多少小孩在看着它。
只要最后一个strong型指针不再指向对象,那么对象就会被释放,同时所有的weak型指针都将会被清除。
弱引用用在哪里
用在block和delegate中
当self拥有一个block的时候,在block又调用self的方法(或者self所拥有的某个属性)。形成你中有我,我中有你,这种时候会造成循环引用。
你拥有一个对象包含了另外了一个实例变量对象,但是第二个对象又把前一个对象作为它的委托,那么这两个对象将不会被释放。
变量是弱引用的话只能用__weak修饰吗?还有什么
修饰delegate,即定义一个delegate的属性时,还可以使用__unsafe_unretain和__weak来修饰,然后通过使用__unsafe_unretain和__weak来单独标记实例变量。这意味着delegate实例变量将仍然能够指向第一个对象,但是它不会导致保留第一个对象,因此打破了retain cycle,而能够释放两个对象。
__unsafe_unretain和__weak都能避免retain cycle,但是他们也有一些细微的不同。对于__weak,当释放指针指向的对象时,该对象的指针将转换为nil,这是比较安全的行为。而__unsafe_unretain,正如其名称隐藏的含义,尽管释放指针指向的对象时,该指针将继续指向原来的内存。这将会导致应用crash,所以是unsafe。
为什么我们仍要使用__unsafe_unretain呢?这是因为__weak直到iOS5.0以及lion之后才出现。
12、数据存储
四种存储方式: 1.NSUserDefaults,用于存储配置信息;2.SQLite,用于存储查询需求较多的数据;3.CoreData,用于规划应用中的对象;4.使用基本对象类型定制的个性化缓存方案.
NSUserDefaults:对象中储存了系统中用户的配置信息,开发者可以通过这个实例对象对这些已有的信息进行修改,也可以按照自己的需求创建新的配置项。
SQLite擅长处理的数据类型其实与NSUserDefaults差不多,也是基础类型的小数据,只是从组织形式上不同。开发者可 以以关系型数据库的方式组织数据,使用SQL DML来管理数据。一般来说应用中的格式化的文本类数据可以存放在数据库 中,尤其是类似聊天记录、Timeline等这些具有条件查询和排序需求的数据。
CoreData是一个管理方案,它的持久化可以通过SQLite、XML或二进制文件储存。它可以把整个应用中的对象建模并进 行自动化的管理。从归档文件还原模型时CoreData并不是一次性把整个模型中的所有数据都载入内存,而是根据运行时状态,把被调用到的对象实例载入内存。框架会自动控制这个过程,从而达到控制内存消耗,避免浪费。 无论从设计原理还是使用方法上看,CoreData都比较复杂。因此,如果仅仅是考虑缓存数据这个需求,CoreData绝对不 是一个优选方案。CoreData的使用场景在于:整个应用使用CoreData规划,把应用内的数据通过CoreData建模,完全 基于CoreData架构应用。 使用基本对象类型定制的个性化缓存方案:从需求出发分析缓存数据有哪些要求:按Key查找,快速读取,写入不影响正常 操作,不浪费内存,支持归档。这些都是基本需求,那么再进一步或许还需要固定缓存项数量,支持队列缓存,缓存过期 等。
13、CALayer层和UIView的关系
UIView和CALayer是相互依赖的关系。UIView依赖与calayer提供的内容,CALayer依赖uivew提供的容器来显示绘制的内容。归根到底CALayer是这一切的基础,如果没有CALayer,UIView自身也不会存在,UIView是一个特殊的CALayer实现,添加了响应事件的能力。UIView来自CALayer,高于CALayer,是CALayer高层实现与封装。UIView的所有特性来源于CALayer支持。
14、代码管理工具git
Git是什么:Git是目前世界上最先进的分布式版本控制系统(没有之一)。
什么是版本控制系统:版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统
集中式 vs分布式
CVS及SVN都是集中式的版本控制系统,而Git是分布式版本控制系统。
集中式和分布式版本控制系统有什么区别呢?
集中式版本控制系统:版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,每个人电脑上都有一个完整的版本库然后开始干活,干完活了,再把自己的活推送给中央服务器。
分布式版本控制系统:每个人的电脑里有完整的版本库,统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。
15、什么是分支,怎样创建分支
终端$ git branch testing
我们知道每次我们commit的时候都会生成一个快照,或者说一个版本库,从引言我们也知道了通过Blob对象存储文件快照内容,然后Tree对象记录快照索引目录,通过索引找到文件快照。
16、runtiem、runloop的实现机制
Runtime:runtime是一套比较底层的纯C语言API,属于1个C语言库,包含了很多底层的C语言API。在我们平时编写的OC代码中,程序运行过程时,其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者.
NSRunLoop是iOS的消息机制的处理模式
1、NSRunloop的主要作用:控制runloop里面线程的执行和休眠,在有事情做的时候使挡墙NSRunloop控制的线程工作,没有事情做让当前runloop的控制线程休眠.
2、runloop就是一直在循环检测,从线程start到线程end,检测inputsourse(如点击,双击等操作)异步时间,检测timesourse同步事件,见到检测到输入源会执行处理函数,首先会产生通知,corefunction向线程添加runloop observers来监听事件,意在监听事件发生时来做处理。
3、runloopmode是一个集合,包括监听:事件源,定时器,以及需通知的runloop observers
runloop在多线程中如何使用
1、只有在为你的程序创建次线程的时候,才需要运行run loop。对于程序的主线程而言,run loop是关键部分。Cocoa提供了运行主线程run loop的代码同时也会自动运行run loop。IOS程序UIApplication中的run方法在程序正常启动的时候就会启动run loop。如果你使用xcode提供的模板创建的程序,那你永远不需要自己去启动run loop
2、在多线程中,你需要判断是否需要run loop。如果需要run loop,那么你要负责配置run loop并启动。你不需要在任何情况下都去启动run loop。比如,你使用线程去处理一个预先定义好的耗时极长的任务时,你就可以毋需启动run loop。Run loop只在你要和线程有交互时才需要
17、自动释放池,如何工作
自动释放池以栈的形式实现:当你创建一个新的自动释放池时,它将被添加到栈顶.当一个对象收到发送autorelease消息时,他被添加到当前线程的处于栈顶的自动释放池中,当自动释放池被回收时,他们从栈中被删除,并且会给池子里面所有的对象都会做一次release操作。1. ojc-c是通过种"referringcounting"(引计数)的方式来管理内存的, 对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一,以后每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0, 就会被系统销毁.
- NSAutoreleasePool 就是用来做引用计数的管理工作的,这个东西一般不你管的.
- autorelease和release没什么区别,只是引计数减一的时机不同而已,autorelease会在对象的使用真正结束的时候才做引计数减一.
18、http和scoket通信的区别?socket连接相关库,TCP,UDP的连接方法,HTTP的几种常用方式?
http和scoket通信的区别: http是客户端用http协议进行请求,发送请求时候需要封装http请求头,并绑定请求的数据,服务器一般有web服务器配 合(当然也非绝对)。 http请求方式为客户端主动发起请求,服务器才能给响应,一次请求完毕后则断开连接,以节省资 源。服务器不能主动给客户端响应(除非采取http长连接技术)。iphone主要使用类是NSUrlConnection。 scoket是客户端跟服务器直接使用socket“套接字”进行连接,并没有规定连接后断开,所以客户端和服务器可以保持连 接通道,双方都可以主动发送数据。一般在游戏开发或股票开发这种要求即时性很强并且保持发送数据量比较大的场合使 用。主要使用类是CFSocketRef。
UDP:是用户数据报协议:主要用在实时性要求高以及对质量相对较弱的地方,但面对现在高质量的线路不是容易丢包除非 是一些拥塞条件下 ,如流媒体
TCP:是传输控制协议:是面连接的,那么运行环境必然要求其可靠性不可丢包有良好的拥塞控制机制如http ftp telnet 等
http的常用方式:get,post