iOS面试题 - 申请后台运行除了后台刷新和VoIP及音乐播放和定位之外还有什么办法?
1、申请后台运行除了后台刷新和voip及音乐播放和定位之外还有什么办法?
uibackgroundtaskidentifier
2、你们项目中为什么多线程用gcd而不用nsoperation呢? 你有没有发现国外的大牛他们多线程都是用nsoperation? 你能告诉我他们这样做的理由吗?
关系:①:先搞清两者的关系,nsopertaionqueue用gcd构建封装的,是gcd的高级抽象!
②:gcd仅仅支持fifo队列,而nsoperationqueue中的队列可以被重新设置优先级,从而实现不同操作的执行顺序调整。gcd不支持异步操作之间的依赖关系设置。如果某个操作的依赖另一个操作的数据(生产者-消费者模型是其中之一),使用nsoperationqueue能够按照正确的顺序执行操作。gcd则没有内建的依赖关系支持。
③:nsoperationqueue支持kvo,意味着我们可以观察任务的执行状态。
了解以上不同,我们可以从以下角度来回答
性能:①:gcd更接近底层,而nsoperationqueue则更高级抽象,所以gcd在追求性能的底层操作来说,是速度最快的。这取决于使用instruments进行代码性能分析,如有必要的话
②:从异步操作之间的事务性,顺序行,依赖关系。gcd需要自己写更多的代码来实现,而nsoperationqueue已经内建了这些支持
③:如果异步操作的过程需要更多的被交互和ui呈现出来,nsoperationqueue会是一个更好的选择。底层代码中,任务之间不太互相依赖,而需要更高的并发能力,gcd则更有优势
3、什么是kvc和kvo?
kvc(key-value-coding)内部的实现:一个对象在调用setvalue的时候,(1)首先根据方法名找到运行方法的时候所需要的环 境参数。(2)他会从自己isa指针结合环境参数,找到具体的方法实现的接口。(3)再直接查找得来的具体的方法实现。kvo(key-value- observing):当观察者为一个对象的属性进行了注册,被观察对象的isa指针被修改的时候,isa指针就会指向一个中间类,而不是真实的类。所以 isa指针其实不需要指向实例对象真实的类。所以我们的程序最好不要依赖于isa指针。在调用类的方法的时候,最好要明确对象实例的类名
4、如何让自己的类用 copy 修饰符?如何重写带 copy 关键字的 setter?
若想令自己所写的对象具有拷贝功能,则需实现 nscopying 协议。如果自定义的对象分为可变版本与不可变版本,那么就要同时实现 nscopying 与 nsmutablecopying 协议。
具体步骤:
1. 需声明该类遵从 nscopying 协议
2. 实现 nscopying 协议的方法。
// 该协议只有一个方法:
- (id)copywithzone:(nszone *)zone;
// 注意:使用 copy 修饰符,调用的是copy方法,其实真正需要实现的是 “copywithzone” 方法。
5、@synthesize 和 @dynamic 分别有什么作用?
@property有两个对应的词,一个是@synthesize(合成实例变量),一个是@dynamic。
如果@synthesize和@dynamic都没有写,那么默认的就是 @synthesize var = _var;
// 在类的实现代码里通过 @synthesize 语法可以来指定实例变量的名字。(@synthesize var = _newvar;)
1. @synthesize 的语义是如果你没有手动实现setter方法和getter方法,那么编译器会自动为你加上这两个方法。
2. @dynamic 告诉编译器,属性的setter与getter方法由用户自己实现,不自动生成(如,@dynamic var)。
6、如何用gcd同步若干个异步调用?(如根据若干个url异步加载多张图片,然后在都下载完成后合成一张整图)
// 使用dispatch group追加block到global group queue,这些block如果全部执行完毕,就会执行main dispatch queue中的结束处理的block。 // 创建队列组 dispatch_group_t group = dispatch_group_create(); // 获取全局并发队列 dispatch_queue_t queue = dispatch_get_global_queue(dispatch_queue_priority_default, 0); dispatch_group_async(group, queue, ^{ /*加载图片1 */ }); dispatch_group_async(group, queue, ^{ /*加载图片2 */ }); dispatch_group_async(group, queue, ^{ /*加载图片3 */ }); // 当并发队列组中的任务执行完毕后才会执行这里的代码 dispatch_group_notify(group, dispatch_get_main_queue(), ^{ // 合并图片 });
7、dispatch_barrier_async(栅栏函数)的作用是什么?
函数定义:dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block); 作用: 1.在它前面的任务执行结束后它才执行,它后面的任务要等它执行完成后才会开始执行。 2.避免数据竞争 // 1.创建并发队列 dispatch_queue_t queue = dispatch_queue_create("myqueue", dispatch_queue_concurrent); // 2.向队列中添加任务 dispatch_async(queue, ^{ // 1.2是并行的 nslog(@"任务1, %@",[nsthread currentthread]); }); dispatch_async(queue, ^{ nslog(@"任务2, %@",[nsthread currentthread]); }); dispatch_barrier_async(queue, ^{ nslog(@"任务 barrier, %@", [nsthread currentthread]); }); dispatch_async(queue, ^{// 这两个是同时执行的 nslog(@"任务3, %@",[nsthread currentthread]); }); dispatch_async(queue, ^{ nslog(@"任务4, %@",[nsthread currentthread]); }); // 输出结果: 任务1 任务2 ——》 任务 barrier ——》任务3 任务4 // 其中的任务1与任务2,任务3与任务4 由于是并行处理先后顺序不定。
8、什么是 runloop
从字面上讲就是运行循环,它内部就是do-while循环,在这个循环内部不断地处理各种任务。
一个线程对应一个runloop,基本作用就是保持程序的持续运行,处理app中的各种事件。通过runloop,有事运行,没事就休息,可以节省cpu资源,提高程序性能。主线程的run loop默认是启动的。ios的应用程序里面,程序启动后会有一个如下的main()函数
int main(int argc, char * argv[]) {
@autoreleasepool {
return uiapplicationmain(argc, argv, nil, nsstringfromclass([appdelegate class]));
}
}
9、runtime实现的机制是什么,怎么用,一般用于干嘛?
1). 使用时需要导入的头文件
10、什么是 tcp / udp ?
tcp:传输控制协议。
udp:用户数据协议。tcp 是面向连接的,建立连接需要经历三次握手,是可靠的传输层协议。
udp 是面向无连接的,数据传输是不可靠的,它只管发,不管收不收得到。
简单的说,tcp注重数据安全,而udp数据传输快点,但安全性一般。