objective-c – NSURLConnection与NSRunLoopCommonModes

objective-c – NSURLConnection与NSRunLoopCommonModes,第1张

概述我为我的iOS应用编写了自己的HTTPClient实现,以异步方式下载指定URL的内容. HTTPClient使用NSOperationQueue将NSURLConnection请求排入队列.我选择了NSOperationQueue因为我想在任何时候取消任何或所有正在进行的NSURLConnection. 我做了很多关于如何实现我的HTTPClient的研究,我有两个选择来执行NSURLConne 我为我的iOS应用编写了自己的httpClIEnt实现,以异步方式下载指定URL的内容. httpClIEnt使用NSOperationQueue将NSURLConnection请求排入队列.我选择了NSOperationQueue因为我想在任何时候取消任何或所有正在进行的NSURLConnection.

我做了很多关于如何实现我的httpClIEnt的研究,我有两个选择来执行NSURLConnection:

1)在单独的辅助线程上执行每个排队的NSURLConnection. NSOperationQueue在后台执行辅助线程上的每个排队 *** 作,因此除了在重写的NSOperation子类的start方法中启动我的NSURLConnection并为生成的辅助线程运行runloop直到connectionDIDFinishLoading或者之外,我不需要做任何显式生成辅助线程的事情.调用connectionDIDFailWithError.它看起来如下:

if (self.connection != nil) {            do {                [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode                                         beforeDate:[NSDate distantFuture]];            } while (!self.isFinished);}

2)在主线程上执行每个排队的NSURLConnection.对于start方法中的这个,我使用performSelectorOnMainThread并在主线程上再次调用start方法.通过这种方法,我使用NSRunLoopCommonModes安排NSURLConnection,如下所示:

[self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

我选择了第二种方法并实施了它.从我的研究来看,第二种方法似乎更好,因为它没有为每个NSURLConnection启动一个单独的辅助线程.现在,在任何时候,在应用程序中可能会有许多请求同时进行,并且使用第一种方法,这意味着将生成相同数量的辅助线程,并且在关联的url请求完成之前不会返回池.

我的印象是我仍然通过使用NSRunLoopCommonModes安排NSURLConnection来同时运行第二种方法.在使用这种方法的其他方面,我认为我使用NSRunLoopCommonModes而不是多线程进行并发,因此NSURLConnection的观察者将尽快调用connectionDIDFinishLaunching或connectionDIDFailWithError,无论主要线程在UI处于哪个主要线程.时间.

不幸的是,今天早上我的一位同事告诉我,当前的实现时,NSURLConnection在其中一个视图控制器上的滚动视图停止滚动之前不会返回.当滚动视图即将停止滚动时,启动NSURLRequest获取数据,但即使它在滚动视图停止调用之前完成,NSURLConnection也不会回调connectionDIDFinishLoading或connectionDIDFailWithError,直到滚动视图完全停止滚动.这意味着在主线程上使用NSRunLoopCommonModes调度NSURLConnection以获得与UI *** 作(触摸/滚动)的真实并发的整个想法被证明是错误的并且NSURLConnection仍然等待直到主线程忙于滚动滚动视图.

我尝试切换到使用辅助线程的第一种方法,它就像一个魅力.当滚动视图仍在滚动时,NSURLConnection仍会调用其协议方法之一.这很清楚,因为现在NSURLConnection没有在主线程上运行,所以它不会等待滚动视图停止滚动.

我真的不想使用第一种方法,因为它由于多线程而很昂贵.

如果我对第二种方法的理解不正确,有人可以告诉我吗?如果它是正确的,使用NSRunLoopCommonModes安排NSURLConnection的原因是什么原因不能按预期工作?

如果答案更具描述性,我将非常感激,因为对于我来说,NSRunLoop和NSRunLoopModes的确切工作方式应该让我更加怀疑.只是为了说明我已经多次阅读过这方面的文档了.

解决方法 事实证明,这个问题比我想象的要简单.

我在NSOperation子类的start方法中有这个

self.connection = [[NSURLConnection alloc] initWithRequest:self.urlRequest                                                              delegate:self];[self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

现在的问题是上面的initWithRequest:delegate:方法实际上使用NSDefaultRunLoopMode在默认的runloop中调度NSURLConnection并完全忽略我实际尝试使用NSRunLoopCommonModes安排它的下一行.通过改变以上两行,按预期工作.

self.connection = [[NSURLConnection alloc] initWithRequest:self.urlRequest                                                              delegate:self startImmediately:NO];[self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];[self.connection start];

这里的实际问题是我必须使用带有参数startImmediately的构造函数方法初始化NSURLConnection.当我为参数startImmediately传递NO时,未使用默认运行循环调度连接.它可以通过调用scheduleInRunLoop:forMode:方法在运行循环和选择模式中进行调度.

现在NSURLConnection从方法scrollVIEwWillEndDragging启动:withVeLocity:targetContentOffset正在调用其委托方法connectionDIDFinishLoading / connectionDIDFailWithError,而滚动视图仍在滚动并且尚未完成滚动.

我希望这可以帮助别人.

总结

以上是内存溢出为你收集整理的objective-c – NSURLConnection与NSRunLoopCommonModes全部内容,希望文章能够帮你解决objective-c – NSURLConnection与NSRunLoopCommonModes所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1238106.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存