面试题一: ios声明变量的属性关键词
@property
@property = ivar + getter + setter;
“属性” (property)有两大概念:ivar(实例变量)、存取方法(accessmethod = getter + setter)。
原子性:nonatomic、atomic
atomic
是默认的
会保证 CPU 能在别的线程来访问这个属性之前,先执行完当前流程
速度不快,因为要保证操作整体完成
nonatomic
不是默认的
更快
线程不安全
如有两个线程访问同一个属性,会出现无法预料的结果
如果该对象无需考虑多线程的情况,这个属性会让编译器少生成一些互斥代码,可以提高效率。
读写权限:readwrite(读写)、readonly (只读)
readwrite 是可读可写特性;需要生成getter方法和setter方法时(补充:默认属性,将生成不带额外参数的getter和setter方法(setter方法只有一个参数))
readonly 是只读特性 只会生成getter方法 不会生成setter方法 ;不希望属性在类外改变
内存管理:assign、weak 、retain 、strong、copy、unsafe_unretained
assign与retain
1、assign: 简单赋值,不更改索引计数;
2、assign的情况:NSString*newPt = [pt assing];
此时newPt和pt完全相同地址都是0Xaaaa 内容为0X1111 即newPt只是pt的别名,对任何一个操作就等于对另一个操作,因此retainCount不需要增加;
3、assign就是直接赋值;
4、retain使用了引用计数,retain引起引用计数加1,release引起引用计数减1,当引用计数为0时,dealloc函数被调用,内存被回收;
weak and strong (强引用和弱引用的区别):
1、weak 和 strong 属性只有在你打开ARC时才会被要求使用,这时你是不能使用retain release autorelease 操作的,因为ARC会自动为你做好这些操作,但是你需要在对象属性上使用weak 和strong,其中strong就相当于retain属性,而weak相当于assign。
2、只有一种情况你需要使用weak(默认是strong),就是为了避免retaincycles(就是父类中含有子类{父类retain了子类},子类中又调用了父类{子类又retain了父类},这样都无法release)
3、声明为weak的指针,指针指向的地址一旦被释放,这些指针都将被赋值为nil。这样的好处能有效的防止野指针。
什么情况下用weak
1、ARC情况下有可能出现循环引用的时候 。可以使用weak 。比如delegate
2、IBoutlet:拖出来的控件属性一般也是weak。当然也可以用strong。
weak与assign 的不同
1、weak为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。然而在属性所指的对象遭到摧毁时,属性值也会清空。
assign基础数据的简单赋值。
2、assign 可以用非 OC 对象,而 weak 必须用于 OC 对象。
怎么用或者什么情况用copy关键字
1、NSString、NSArray、NSDictionary等等经常使用copy关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary;
2、block 也经常使用 copy 关键字。
注意 1:只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的。
2、另一个需要注意的问题是关于线程安全。
在声明Block属性时需要确认“在调用Block时另一个线程有没有可能去修改Block?如果确定不会有这种情况发生的话,那么Block属性声明可以用nonatomic。如果会有这种情况发生的话,那么你首先需要声明Block属性为atomic;在非ARC下则需要手动retain一下,否则如果属性被置空,本地变量就成了野指针了,也要记着release。
copy 与 retain的区别
1、copy其实是建立了一个相同的对象,而retain不是
2、copy是内容拷贝,retain是指针拷贝;
3、copy是内容的拷贝 ,对于像NSString,的确是这样,但是如果copy的是一个NSArray呢?这时只是copy了指向array中相对应元素的指针.这便是所谓的"浅复制”.
@synthesize和@dynamic分别有什么作用?
@property有两个对应的词,一个是@synthesize,一个是 @dynamic。如果 @synthesize和 @dynamic都没写,那么默认的就是@syntheszie var = _var;
@synthesize 的语义是如果你没有手动实现 setter 方法和 getter 方法,那么编译器会自动为你加上这两个方法。
@dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。(当然对于 readonly 的属性只需提供 getter 即可)。假如一个属性被声明为 @dynamic var,然后你没有提供 @setter方法和 @getter 方法,编译的时候没问题,但是当程序运行到 instance.var = someVar,由于缺 setter 方法会导致程序崩溃;或者当运行到 someVar = var 时,由于缺 getter 方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。
__block和__weak修饰符的区别其实是挺明显的:
1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。
2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。
3.__block对象可以在block中被重新赋值,__weak不可以。
GCD里面用 __weak 防止内存释放不了,循环引用。
面试题二:IOS网络
一、底层实现
1、AFN的底层实现基于OC的NSURLConnection和NSURLSession
2、ASI的底层实现基于纯C语言的CFNetwork框架
3、因为NSURLConnection和NSURLSession是在CFNetwork之上的一层封装,因此ASI的运行性能高于AFN
二、对服务器返回的数据处理
1、ASI没有直接提供对服务器数据处理的方式,直接返回的是NSData/NSString
2、AFN提供了多种对服务器数据处理的方式
(1)JSON处理-直接返回NSDictionary或者NSArray
(2)XML处理-返回的是xml类型数据,需对其进行解析
(3)其他类型数据处理
三、监听请求过程
1、AFN提供了success和failure两个block来监听请求的过程(只能监听成功和失败)
success : 请求成功后调用
failure : 请求失败后调用
2、ASI提供了3套方案,每一套方案都能监听请求的完整过程
(监听请求开始、接收到响应头信息、接受到具体数据、接受完毕、请求失败)
成为代理,遵守协议,实现协议中的代理方法
成为代理,不遵守协议,自定义代理方法
设置block
四、在文件下载和文件上传的使用难易度
1、AFN
不容易实现监听下载进度和上传进度】 不容易实现断点续传、一般只用来下载不大的文件
2、ASI
非常容易实现下载和上传 非常容易监听下载进度和上传进度
非常容易实现断点续传 下载大文件或小文件均可
3、实现下载上传推荐使用ASI
五、网络监控
1、AFN自己封装了网络监控类,易使用
2、ASI使用的是Reachability,因为使用CocoaPods下载ASI时,会同步下载Reachability,但Reachability作为网络监控使用较为复杂(相对于AFN的网络监控类来说)
3、推荐使用AFN做网络监控-AFNetworkReachabilityManager
六、ASI提供的其他实用功能
1、控制信号旁边的圈圈要不要在请求过程中转
2、可以轻松地设置请求之间的依赖:每一个请求都是一个NSOperation对象
3、可以统一管理所有请求(还专门提供了一个叫做ASINetworkQueue来管理所有的请求对象)
暂停/恢复/取消所有的请求
监听整个队列中所有请求的下载进度和上传进度
七、网络层级
第一部分:IOS关于网络请求的接口自下至上有如下几层:
· CFSocket 是最底层的接口,只负责 socket 通信。
· CFNetwork 是基于 CFSocket 等接口的上层封装,ASIHttpRequest 工作于这一层。
· NSURLConnection 是基于 CFNetwork 的更高层的封装,提供面向对象的接口,AFNetworking 工作于这一层。
· NSURLSession 是 iOS7 中新增的接口,表面上是和 NSURLConnection 并列的,但底层仍然用到了 NSURLConnection 的部分功能 (比如 com.apple.NSURLConnectionLoader 线程),AFNetworking2和 Alamofire 工作于这一层。
第二部分:各协议的区别
1、网络七层由下往上分别为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。
2、其中物理层、数据链路层和网络层通常被称作媒体层,是网络工程师所研究的对象;
3、传输层、会话层、表示层和应用层则被称作主机层,是用户所面向和关心的内容。
http协议 对应于应用层 ,HTTP协议是基于TCP连接的。HTTP是应用层协议,主要解决如何包装数据。
tcp协议 对应于传输层 , TCP/IP是传输层协议,主要解决数据如何在网络中传输;
ip协议 对应于网络层
Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
建立起一个TCP连接需要经过“三次握手”:
1.TCP是有连接的,可靠的、可控制的、无边界的socket通信。
2.UDP是无连接的、不可靠的 数据报通信。但是效率高。
面试题三 :ios消息传递
iOS通讯模式(KVO、Notification、Delegate、Block、Target-Action的区别)
KVO
一、delegate(委托):
代理更注重过程信息的传输:比如发起一个网络请求,可能想要知道此时请求是否已经开始、是否收到了数据、数据是否已经接受完成、数据接收失败1,“一对一”,对同一个协议,一个对象只能设置一个代理delegate,所以单例对象就不能用代理;
二、block
block 常见的几种场景:回调、传参。
1:写法更简练,不需要写protocol、函数等等
2,block注重结果的传输:比如对于一个事件,只想知道成功或者失败,并不需要知道进行了多少或者额外的一些信息
3,block需要注意防止循环引用:
4、block出栈需要将使用的数据从栈内存拷贝到堆内存,当然对象的话就是加计数,使用完或者block置nil后才消除;delegate只是保存了一个对象指针,直接回调,没有额外消耗。相对C的函数指针,只多做了一个查表动作
第三:notification(通知)
“一对多”,在APP中,很多控制器都需要知道一个事件,应该用通知
面试题四:runloop
简介:runloop 其实就是一个一直运行的循环。用于等等和 处理 各种事件。一个线程一次只能执行一个任务,执行完成后线程就会退出。如果我们需要一个机制,让线程能随时处理事件但并不退出,通常的代码逻辑是这样的。
function loop() {
initialize();
do {
varmessage = get_next_message();
process_message(message);
} while (message !=quit);
}
面试题五:多线程
(一)NSThread
优点:NSThread 比其他两个轻量级
缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销.
(二)Cocoa NSOperation
简介:NSOperation
NSOperationQueue
NSOperation是个抽象类,使用它必须用它的子类,可以实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。
优点:1、不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上。
2、设置线程执行的优先级。
3、可以控制线程 的状态。比如(开始start)、(取消 clean)
4、添加依赖关系。(但是要)
添加依赖关系要注意一下3点:
1.不要建立循环依赖,会造成死锁,原因同循环引用
2.使用依赖建议只使用NSInvocationOperation,NSInvocationOperation和NSBlockOperation混用会导致依赖关系无法正常实现。
3.依赖关系不光在同队列中生效,不同队列的NSOperation对象之前设置的依赖关系一样会生效
(三)GCD(全称:Grand Central Dispatch)
Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。在iOS4.0开始之后才能使用。GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的很高效和强大的技术。现在的iOS系统都升级到7了,所以不用担心该技术不能使用。
GCD会自动根据任务在多核处理器上分配资源,优化程序。系统给每一个应用程序提供了三个concurrent dispatch queues。这三个并发调度队列是全局的,它们只有优先级的不同。因为是全局的,我们不需要去创建。我们只需要通过使用函数dispath_get_global_queue去得到队列,如下:
dispatch_group_async
dispatch_group_async可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。这个方法很有用,比如你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成的了dispatch_barrier_async是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行
runtime
1、objective_c 是一门动态语言,在编译是不能决定调用哪个函数。只有在运行时才能决定调用那些函数。
2、runTime 基本上是C和汇编写的。
3、与runtime 系统交互:1、objectIve _c源代码。2、Foundation 框架的NSObject 定义方法 3、runTime函数直接调用。
4、进行消息发送和转发。
面试题七:项目实战
问题一:tableView 滑动卡的问题主要是因为。
原因:tableView 滑动卡的问题主要是因为:从缓存中或者是从本地读取图片给UIImage的时候耗费的时间。
问题二:在单利中创建数组应该注意些什么。