注册

AFNetWorking为何在发起请求时要通过runloop!OC 中常用关键字的区别!

最近几天经历了多场面试,由于简历上写了runloop,跟AFNetworing的字眼。面试官好像特别喜欢问这个问题。一连几场都遇到。

可惜平时开发过程中,知识的累计跟沉淀不足。都不能回答的很好..


趁着现在有时间。查阅一下资料 在这里进行一个总结。。

Question:AFNetworking 2.x怎么开启常驻子线程?为何需要常驻子线程?对应以下代码:


+ (void)networkRequestThreadEntryPoint:(id)__unused object {
@autoreleasepool {
[[NSThread currentThread] setName:@"AFNetworking"];

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
}

+ (NSThread *)networkRequestThread {
static NSThread *_networkRequestThread = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
[_networkRequestThread start];
});

return _networkRequestThread;
}

首先,我们要了解为何要开启常驻子线程?

NSURLConnection的接口是异步的,然后会在发起的线程回调。而一个子线程,在同步代码执行完成之后,一般情况下,线程就退出了。那么想要接收到NSURLConnection的回调,就必须让子线程至少存活到回调的时机。而AF让线程常驻的原因是,当发起多个http请求的时候,会统一在这个子线程进行回调的处理,所以干脆就让其一直存活下来。

上面说的一般情况,子线程执行完任务就会退出,那么什么情况下,子线程能够继续存活呢?这就涉及到第二个问题了,AF是如何开启常驻线程的,这里实际上考察的是runloop的基础知识。

这里简单来说,当runloop发现还有source/timer/observer的时候,runloop就不会退出。所以AF这里就通过给当前runloop添加一个NSMachPort,这个port实际上相对于添加了一个source事件源,这样子线程的runloop就会一直处于循环状态,等待别的线程向这个port发送消息,而实际上AF这里是没有消息发送到这个port的。


OC 中 strong, weak, assign, copy 的区别

strong

强引用,只可以修饰对象,属性的默认修饰符,其修饰的对象引用计数增加1

weak

弱引用,只可以修饰对象,指向但不拥有对象,其修饰的对象引用计数不增加,可以避免循环引用,weak修饰的对象释放后,指针会被系统置为nil,此时向对象发送消息不会奔溃

assign

可以修饰对象和基本数据类型,如果修饰对象,其修饰的对象引用计数不增加,可以避免循环引用,但assign修饰的对象释放后,指针不会被系统置为nil,这会产生野指针的问题,此时向对象发送消息会奔溃。所以assign通常用于基本数据类型,如int ,float, NSInteger, CGFloat ,这是因为基本数据类型放在栈区,先进先出,基本数据类型出栈后,assign修饰的变量就不存在了,不用担心指针的问题。

copy

引用,修饰不可变的对象,比如NSString, NSArray, NSDictionary。copy和strong类似,不同之处在于,copy修饰的对象会先在内存中拷贝一个新的对象,copy会指向那个新的对象的内存地址,这样避免了多个指针指向同一对象,而导致的其中一个指针改变了对象,其他指针指向的对象跟着改变,举个例子:

@property(strong) NSString *name1;
@property(copy) NSString *name2;

NSMutableString *name3 = [NSMutableString stringWithString:@"Danny"];
self.name1 = name3;
self.name2 = name3;
[name3 setString:@"Liming"];
NSLog(@"%@", self.name1); // Liming
NSLog(@"%@", self.name2); // Danny

我们可以看到使用strong的属性name1会跟着name3变,因为他们都指向同一个NSMutableString的对象,而name2预先拷贝了name1,从而避免了和name1一起变化。

copy的原则就是,把一个对象赋值给一个属性变量,当这个对象变化了,如果希望属性变量变化就使用strong属性,如果希望属性变量不跟着变化,就是用copy属性。






0 个评论

要回复文章请先登录注册