网络iOS:后台/主线程?
我想在手机里放个图像。 如果图像已经加载(因此,在缓存中),我会这样做。否则,我将使用网络iOS:后台/主线程?,ios,multithreading,background,nsurlconnection,nsurlsession,Ios,Multithreading,Background,Nsurlconnection,Nsurlsession,我想在手机里放个图像。 如果图像已经加载(因此,在缓存中),我会这样做。否则,我将使用sendaynchronousrequest在后台下载它 这是我的代码: var image = self.imageCached[urlString] as? UIImage if image { cell.imageView.image = image } else { let request = NSURLRequest
sendaynchronousrequest
在后台下载它
这是我的代码:
var image = self.imageCached[urlString] as? UIImage
if image {
cell.imageView.image = image
} else {
let request = NSURLRequest(URL: NSURL(string: urlString))
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), { response, data, error -> Void in
image = UIImage(data: data)
self.imageCached[urlString] = image;
dispatch_async(dispatch_get_main_queue(), {
cell.imageView.image = image
})
})
}
但我还有一些不清楚的地方:
NSURLConnection.sendAsynchronousRequest
正在后台执行任务,但NSOperationQueue.mainQueue()
似乎在主线程中执行任务(因为名称为“mainQueue”)。那么什么是真正的事情呢?指令中的块是在后台还是在主线程中?因为如果它在主线程上,则不必返回主线程来更新UI
NSURLConnection
用于小的快速请求。这是真的吗?因为当我使用NSURLSession
而不是此异步NSURLConnection
请求下载所有单元格图像时,NSURLConnection
的时间更长
那么我应该在何时使用NSURLConnection
以及何时使用nsursession
?(例如:json数据或来自api的快速登录检查)
queue
参数指定在哪个队列上运行完成块,而不是在哪个队列上执行网络操作
另一方面,这意味着在完成块/闭包的当前实现中对主队列的额外调度是多余的
请注意,有点令人惊讶的是,imageWithData
本身可能(特别是如果图像较大)运行时间超过几毫秒,如果在主线程中执行imageWithData
,则可能会导致UI中出现明显(尽管非常轻微)的口吃。一般来说,您甚至不会注意到这一点,但如果这段代码位于表/集合视图中,您将看到它是否快速滚动。因此,您可能希望使用除mainQueue
之外的操作队列作为网络请求的queue
参数,然后保留将最终UI更新发送到主队列的代码。差别可能不太明显,但如果你想保持滚动的丝般光滑,这是一个改进。这取决于代码出现的上下文NSURLSession
比NSURLConnection
慢。我想知道(尤其是在没有看到nsursession
实现的代码的情况下),您的nsursession
实现是否出于某种原因没有缓存
总顾问建议,如果需要支持7.0之前的iOS版本,您可以使用NSURLConnection
,否则请使用NSURLSession
NSURLConnection
和/或nsursession
透明提供的,完全独立于您可能对阵列有效执行的任何应用程序级缓存谢谢你的回复。关于1)我什么也不懂^^^关于第2点,我看到了您与我们简要分享的
nsursession
示例,但没有看到任何明显的内容。我刚刚比较了nsursession.sharedSession()
,nsursession(配置)
,和NSURLConnection.sendAsynchronousRequest
,它们是可比的,因此我不能在没有更多信息的情况下发表评论(包括显示您描述的行为的示例URL)。我唯一想知道的是,这两个类之间的默认缓存可能存在差异(苹果对特定标准从来都不是很开放),但这可以通过显式指定缓存来弥补。对不起,关于Rob,这只是我的一个错误。没关系。但正如我所说,现在问题不在我,而在我。。无论如何,感谢您所做的一切。很抱歉,我不清楚您是否还有任何问题,或者我是否已经回答了…顺便说一句,如果这是在表/集合视图中,请记住,您不能假设异步请求完成时,单元格
仍然有效(因为单元格被重用)。通常,在dispatch\u async
块中,您可以使用cellForXXXAtIndexPath
查询表/集合视图(不要与视图控制器中类似命名的方法混淆),以查看单元格是否仍然可见,并使用新指针更新图像。好的,调度之外的单元格呢(在第一个if中),它可能是无效的?第一个if(你说if image…
)是可以的,因为这是在cellforrowatinedexpath
的流中同步发生的。但是异步请求中的任何内容(例如sendsynchronousrequest
)或者在dispatch\u async
中,在尝试使用之前,应该检查单元格是否仍然可见。如果不这样做,尤其是在慢速连接中,您可能会看到错误的单元格被更新(这有时会表现为单元格图像从一个到另一个闪烁)。