I've looked at a lot of topics but I still can't figure it out.
我看了很多话题,但我仍然无法理解。
I have a UITableview which downloads its content online. Each cell has an image, and I use GCD to let the image download. The downloaded image will be saved to disk, and before each time a cell is loaded there is checked if the file already exist, if not -> gcd, nsdata etc.
我有一个UITableview在线下载其内容。每个单元格都有一个图像,我使用GCD让图像下载。下载的图像将保存到磁盘,每次加载单元格之前,都会检查文件是否已经存在,如果不存在 - > gcd,nsdata等。
All goes well if someone has a good internet connection (wifi), but if I'm going to hop from View to View (back and forth), with my crappy 3G connection, what happens is that it wants to finish its queue (about 4 cells), but already gets assigned a new one, and a new one, and a new one and eventually the user has to wait a looong time before the others are executed (which he doesnt see) before the actual UITableview gets populated. With NSLog I can see that even I'm in a different view, it's still downloading and making uiimages that were visible on the screen. Each task is approximately 100 kb, and with a slow (or even no internet connection?!) it can take a while if you have a lot.
如果有人有一个良好的互联网连接(wifi),一切顺利,但如果我要从View到View(来回)跳跃,我蹩脚的3G连接,会发生什么,它想要完成它的队列(关于4个单元格,但已经分配了一个新的,一个新的,一个新的,最终用户必须等待一段时间才能执行其他人(他没有看到),然后才能填充实际的UITableview。使用NSLog,我可以看到,即使我处于不同的视图中,它仍在下载并制作在屏幕上可见的uiimages。每个任务大约100 kb,并且速度很慢(甚至没有互联网连接?!)如果你有很多,它可能需要一段时间。
I know it's not possible to cancel it, but I read in other topics about using a BOOL variable but I don't really get it. Even if the BOOL variable change when the user leaves the screen, the cells are already in queue right?
我知道取消它是不可能的,但是我读到了关于使用BOOL变量的其他主题,但我并没有真正理解它。即使BOOL变量在用户离开屏幕时发生变化,单元格也已排在队列中?
Is it possible that when a user taps the back button in my Navigationcontroller, so he leaves the view, I change the data the blocks in queue use (empty it), so there is nothing to download and the blocks will be executed right away (there is nothing to do). So something like, making every value in array newsitems nil? Is it possible to change the datasource, or will the blocks that are waiting already have their datasource with them while waiting?
是否有可能当用户点击我的Navigationcontroller中的后退按钮,所以他离开视图时,我更改了队列中使用的块的数据(清空它),因此没有任何内容可以下载,并且块将立即执行(没有什么可以做的)。这样的事情,使数组newsitems中的每个值都为零?是否可以更改数据源,或者等待的块在等待时是否已经拥有了数据源?
Then there is another problem, this doesn't have effect on the the currently executed block.
然后还有另一个问题,这对当前执行的块没有影响。
Can someone point me in a good direction?
有人能指出我的方向吗?
Thank you.
谢谢。
Prastow
Prastow
2 个解决方案
#1
1
You can make use of NSBlockOperation
and NSOperationQueue
to create a cancellable download task. You create an NSBlockOperation
by giving it a block which performs some work. In your case the block would download the contents of the URL.
您可以使用NSBlockOperation和NSOperationQueue来创建可取消的下载任务。您可以通过为其执行一些工作来创建一个NSBlockOperation。在您的情况下,块将下载URL的内容。
In your view controller, you would store a list of the operations that have been submitted to the queue. If the user decides to leave the current view, you can then call cancel
on each of the pending operations to prevent any needless work from taking place. The currently running operation will run to completion however. In order to cancel the currently running operation, you need to store a weak reference to the NSOperation object in the block doing teh work. Then at appropriate intervals within the body of the block, you can check to see if the operation has been cancelled and exit early.
在视图控制器中,您将存储已提交到队列的操作列表。如果用户决定离开当前视图,则可以对每个待处理操作调用取消,以防止发生任何不必要的工作。但是,当前正在运行的操作将完成。为了取消当前运行的操作,您需要在执行工作的块中存储对NSOperation对象的弱引用。然后,在块体内的适当间隔,您可以检查操作是否已取消并提前退出。
// Create a queue on which to run the downloads
NSOperationQueue* queue = [NSOperationQueue new];
// Create an operation without any work to do
NSBlockOperation* downloadImageOperation = [NSBlockOperation new];
// Make a weak reference to the operation. This is used to check if the operation
// has been cancelled from within the block
__weak NSBlockOperation* operation = downloadImageOperation;
// The url from which to download the image
NSURL* imageURL = [NSURL URLWithString:@"http://www.someaddress.com/image.png"];
// Give the operation some work to do
[downloadImageOperation addExecutionBlock: ^() {
// Download the image
NSData* imageData = [NSData dataWithContentsOfURL:imageURL];
// Make sure the operation was not cancelled whilst the download was in progress
if (operation.isCancelled) {
return;
}
// Do something with the image
}];
// Schedule the download by adding the download operation to the queue
[queue addOperation:imageDownloadOperation];
// As necessary
// Cancel the operation if it is not already running
[imageDownloadOperation cancel];
A good talk on this exact topic was given at WWDC this year entitled "Building Concurrent User Interfaces on iOS". You can find the video and slides here
今年在WWDC上发表了题为“在iOS上构建并发用户界面”的精彩话题。您可以在此处找到视频和幻灯片
#2
0
I faced similar issues with an app I developed a while back and found that the best way to do everything you require, and more, is to use https://github.com/MugunthKumar/MKNetworkKit
我在一段时间内开发的应用程序遇到了类似的问题,并发现做所需的一切的最佳方法,更多的是使用https://github.com/MugunthKumar/MKNetworkKit
It took me the best part of a day to learn and understand the conversion and then a couple more days to tweak it to exactly what I needed.
我花了一天的时间来学习和理解转换,然后花了几天时间将它调整到我需要的地方。
If you do decide to use it or would like a thorough overview of the capabilities start here http://blog.mugunthkumar.com/products/ios-framework-introducing-mknetworkkit/
如果您决定使用它或希望全面了解这些功能,请访问http://blog.mugunthkumar.com/products/ios-framework-introducing-mknetworkkit/
#1
1
You can make use of NSBlockOperation
and NSOperationQueue
to create a cancellable download task. You create an NSBlockOperation
by giving it a block which performs some work. In your case the block would download the contents of the URL.
您可以使用NSBlockOperation和NSOperationQueue来创建可取消的下载任务。您可以通过为其执行一些工作来创建一个NSBlockOperation。在您的情况下,块将下载URL的内容。
In your view controller, you would store a list of the operations that have been submitted to the queue. If the user decides to leave the current view, you can then call cancel
on each of the pending operations to prevent any needless work from taking place. The currently running operation will run to completion however. In order to cancel the currently running operation, you need to store a weak reference to the NSOperation object in the block doing teh work. Then at appropriate intervals within the body of the block, you can check to see if the operation has been cancelled and exit early.
在视图控制器中,您将存储已提交到队列的操作列表。如果用户决定离开当前视图,则可以对每个待处理操作调用取消,以防止发生任何不必要的工作。但是,当前正在运行的操作将完成。为了取消当前运行的操作,您需要在执行工作的块中存储对NSOperation对象的弱引用。然后,在块体内的适当间隔,您可以检查操作是否已取消并提前退出。
// Create a queue on which to run the downloads
NSOperationQueue* queue = [NSOperationQueue new];
// Create an operation without any work to do
NSBlockOperation* downloadImageOperation = [NSBlockOperation new];
// Make a weak reference to the operation. This is used to check if the operation
// has been cancelled from within the block
__weak NSBlockOperation* operation = downloadImageOperation;
// The url from which to download the image
NSURL* imageURL = [NSURL URLWithString:@"http://www.someaddress.com/image.png"];
// Give the operation some work to do
[downloadImageOperation addExecutionBlock: ^() {
// Download the image
NSData* imageData = [NSData dataWithContentsOfURL:imageURL];
// Make sure the operation was not cancelled whilst the download was in progress
if (operation.isCancelled) {
return;
}
// Do something with the image
}];
// Schedule the download by adding the download operation to the queue
[queue addOperation:imageDownloadOperation];
// As necessary
// Cancel the operation if it is not already running
[imageDownloadOperation cancel];
A good talk on this exact topic was given at WWDC this year entitled "Building Concurrent User Interfaces on iOS". You can find the video and slides here
今年在WWDC上发表了题为“在iOS上构建并发用户界面”的精彩话题。您可以在此处找到视频和幻灯片
#2
0
I faced similar issues with an app I developed a while back and found that the best way to do everything you require, and more, is to use https://github.com/MugunthKumar/MKNetworkKit
我在一段时间内开发的应用程序遇到了类似的问题,并发现做所需的一切的最佳方法,更多的是使用https://github.com/MugunthKumar/MKNetworkKit
It took me the best part of a day to learn and understand the conversion and then a couple more days to tweak it to exactly what I needed.
我花了一天的时间来学习和理解转换,然后花了几天时间将它调整到我需要的地方。
If you do decide to use it or would like a thorough overview of the capabilities start here http://blog.mugunthkumar.com/products/ios-framework-introducing-mknetworkkit/
如果您决定使用它或希望全面了解这些功能,请访问http://blog.mugunthkumar.com/products/ios-framework-introducing-mknetworkkit/