-app具有用于运行NSURLConnection的串行队列
-app订阅了connectionDidFinishLoading事件
-app使得简单的' ping'到站点并在队列中运行CFRunLoopRun以启用事件
-app在收到connectionDidFinishLoading事件后关闭连接, 在CFRunLoopRun退出时,我们记录它并在退出队列任务后,另一个任务将收到执行槽
- 但如果我们添加Realm,那么CFRunLoopRun将无限期运行,现在我们的队列被锁定
我还打开了票https://github.com/realm/realm-cocoa/issues/4737
#import "Realm/Realm.h"
@interface ViewController () <NSURLConnectionDataDelegate>
@end
@implementation ViewController {
dispatch_queue_t my_queue;
NSURLConnection *_connection;
}
- (void)viewDidLoad {
[super viewDidLoad];
my_queue = dispatch_queue_create("my queue", NULL);
dispatch_async(my_queue, ^{
[RLMRealm defaultRealm]; // (1) // comment to make it running
NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://google.com"]];
_connection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
CFRunLoopRun(); // (2) infinite loop inside ios so (3) and (4) as result never been called
NSLog(@"done"); // (3)
});
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
dispatch_async(my_queue, ^{
NSLog(@"test"); // (4) // never been called when realm is used in the same queue
});
_connection = nil; // (5) // without (1) this line stops runloop so (2) and (3) will be called
}
答案 0 :(得分:0)
CFRunLoopRun
以默认模式运行runloop,直到删除所有源和计时器,或调用CFRunLoopStop
。您的代码似乎是在没有其他人会在该runloop上添加runloop源或注册计时器的情况下运行的,并且当您的网络请求结束时,所有runloop源都将被删除。我不认为对您调用的任何第三方代码的行为做出假设是安全的,无论是Realm还是Apple。
此外,我建议不要在调度队列上运行runloop。 Dispatch对由有限数量的系统拥有的线程服务的队列进行排队,并且在等待网络请求时将其阻塞不确定的时间量。 NSURLConnection
很乐意让你schedule the connection on a different runloop,例如主线程的runloop,甚至是schedule delegate callbacks to happen on a dispatch queue。
如果你绝对必须继续在这样的调度队列上运行runloop,你应该使用一些显式信号来确定何时停止运行runloop然后调用CFRunLoopStop
。我建议不要这样做。