NSOperation + Objective-C类别=糟糕的想法?

时间:2022-09-07 10:50:56

I've set up an Objective-C category for an iPhone app's UIImageView class. The category's mission is to help load URL-based images asynchronously with memory/disk caching.

我为iPhone应用程序的UIImageView类设置了Objective-C类别。该类别的任务是帮助加载与内存/磁盘缓存异步的基于URL的映像。

Now, in UIImageView+Cache.m I have access to an NSOperationQueue so I can kick off a loading thread. I create an NSOperation-derived object, initialized with the image URL and the target UIImageView, and a selector to perform on the target once the operation is complete. In the selector method, we set our freshly-loaded image (or, if not found, we set an alternate placeholder image), and we're done!

现在,在UIImageView + Cache.m中,我可以访问NSOperationQueue,因此我可以启动加载线程。我创建了一个NSOperation派生的对象,用图像URL和目标UIImageView初始化,以及一个操作完成后在目标上执行的选择器。在选择器方法中,我们设置新加载的图像(或者,如果没有找到,我们设置一个替代占位符图像),我们就完成了!

This works fine, until a UIImageView happens to be removed before the NSOperation completes. For instance, I have a previous/next segmented control in my UI that causes these UIImageViews to be removed and added anew (they're part of a larger "item" that is being viewed in the app), so it's very easy to tap these in rapid succession.

这很好,直到在NSOperation完成之前碰巧删除了UIImageView。例如,我的UI中有一个上一个/下一个分段控件,导致这些UIImageViews被删除并重新添加(它们是应用程序中正在查看的较大“项目”的一部分),因此很容易点击这些快速连续。

So if you decide to start tapping away before all the images are loaded - KABLAM! Unhappy thread has an invalid object and doesn't know it. :(

因此,如果您决定在加载所有图像之前开始使用 - KABLAM!不开心的线程有一个无效的对象,并不知​​道它。 :(

The closest thing I can find to help mitigate this is NSOperation's cancel and isCancelled methods, except you can't keep track of which operation object to cancel within a Category, because - if I understand correctly - Categories can't add IVARs to objects!

我能找到的最接近帮助缓解这一点的是NSOperation的cancel和isCancelled方法,除非你无法跟踪要在一个类别中取消哪个操作对象,因为 - 如果我理解正确 - 类别不能将IVAR添加到对象!

Maybe that means Categories aren't a good idea here? (Whines: "But I liiiiike Categories! Waaah!")

也许这意味着类别在这里不是一个好主意? (呜呜声:“但我是liiiiike类别!Waaah!”)

Advisement appreciated!

3 个解决方案

#1


I probably wouldn't use a category for this situation. Categories are useful, but are usually unnecessary. I'd only use a category if you have a really good reason to. What exactly are you putting in the category?

我可能不会在这种情况下使用类别。类别很有用,但通常是不必要的。如果你有充分的理由,我只会使用一个类别。你究竟在这个类别中投入了什么?

I think you could implement the whole thing in the NSOperation subclass, which would be the best solution. Put a retain on the image view so it doesn't get deallocated before the image is downloaded, and cancel the download if the view is not visible anymore. If that's not possible, then subclass UIImageView instead of using a category.

我认为你可以在NSOperation子类中实现整个过程,这将是最好的解决方案。在图像视图上放置一个保留,以便在下载图像之前不会取消分配,如果视图不再可见,则取消下载。如果那是不可能的,那么子类UIImageView而不是使用类别。

#2


I would say there is no harm in moving this into your own UIImageView subclass. Sure, you may like categories - but if they don't do the job then why hesitate in moving to a design that does?

我想说将它移动到你自己的UIImageView子类中是没有害处的。当然,你可能喜欢类别 - 但如果他们不做这个工作那么为什么不愿意转向设计呢?

#3


Are you retaining the UIImageView by the NSOperation? Otherwise the imageView might be freed before the NSOperation completes, leading to kablooi central. You should do a retain and then, once you've done the setImage, do a release.

您是否通过NSOperation保留UIImageView?否则,在NSOperation完成之前可能会释放imageView,从而导致kablooi中心。你应该做一个保留,然后,一旦你完成了setImage,就做一个发布。

#1


I probably wouldn't use a category for this situation. Categories are useful, but are usually unnecessary. I'd only use a category if you have a really good reason to. What exactly are you putting in the category?

我可能不会在这种情况下使用类别。类别很有用,但通常是不必要的。如果你有充分的理由,我只会使用一个类别。你究竟在这个类别中投入了什么?

I think you could implement the whole thing in the NSOperation subclass, which would be the best solution. Put a retain on the image view so it doesn't get deallocated before the image is downloaded, and cancel the download if the view is not visible anymore. If that's not possible, then subclass UIImageView instead of using a category.

我认为你可以在NSOperation子类中实现整个过程,这将是最好的解决方案。在图像视图上放置一个保留,以便在下载图像之前不会取消分配,如果视图不再可见,则取消下载。如果那是不可能的,那么子类UIImageView而不是使用类别。

#2


I would say there is no harm in moving this into your own UIImageView subclass. Sure, you may like categories - but if they don't do the job then why hesitate in moving to a design that does?

我想说将它移动到你自己的UIImageView子类中是没有害处的。当然,你可能喜欢类别 - 但如果他们不做这个工作那么为什么不愿意转向设计呢?

#3


Are you retaining the UIImageView by the NSOperation? Otherwise the imageView might be freed before the NSOperation completes, leading to kablooi central. You should do a retain and then, once you've done the setImage, do a release.

您是否通过NSOperation保留UIImageView?否则,在NSOperation完成之前可能会释放imageView,从而导致kablooi中心。你应该做一个保留,然后,一旦你完成了setImage,就做一个发布。