在 ipad 应用程序中处理许多 ASIHttpRequest 和核心数据操作的最佳方法
我当前为 iPad 开发的应用程序涉及处理许多网络请求并将处理后的结果保存在核心数据中。
场景如下 - 应用程序需要下载我在网格视图中显示的对象的图像,该视图总共可以显示 30 个对象。每个对象最多可以包含 15 张 png 图像(也在网格中)。由于服务器的实现方式(意味着我没有实现它并且无法轻松更改它),每个图像必须单独请求,因此我需要为每个对象发出最多 15 个请求,而不是下载所有图像的 1 个请求15 张图片。
对于每个对象,我当前使用 ASINetworkQueue 对 15 个图像请求进行排队。队列完成后,我创建该对象的缩略图快照及其要在网格中显示的图像,然后将所有 png 文件保留到核心数据。
目前,除了由 ASI 异步处理的网络请求之外,我正在主线程上运行所有内容,但由于请求太多,应用程序 UI 基本上处于锁定状态,直到所有请求都得到处理并将结果保存到核心数据中。
我遇到的一种解决方案是在单独的线程中执行核心数据操作和写入或使用中央调度。另一种方法是仅下载可见对象的图像,并在用户向下滚动时下载其余部分。
我正在寻找其他建议来帮助保持主用户界面的响应能力,或者更好的方法来构建网络和核心数据操作。谢谢。
The current app I'm developing for the iPad involves handling many network requests and persisting the processed results in core data.
The scenario is follows - the application needs to download images for objects I'm displaying in a grid view, which can show a total of 30 objects. Each object can consist of up to 15 png images (also in a grid). Due to the way the server is implemented (meaning I didn't implement it and can't change it easily), each image must be requested separately, so I need to make up to 15 requests per object versus just 1 request to download all 15 images.
For each object, I'm currently using an ASINetworkQueue to queue up the 15 image requests. Once the queue finishes, I create a thumbnail snapshot of the object with its images to display in the grid, then persist all the png files to core data.
I'm currently running everything on the main thread except the network requests which are handled by ASI asynchronously, but since there are so many requests, the app UI is essentially locked until all the requests are processed and results saved to core data.
One solution I came across was doing the core data operations and writes in a separate thread or using grand central dispatch. Another is to only download the images for the visible objects, and download the rest when the user scrolls down.
I'm looking for other suggestions to help keep the main ui responsive, or better ways to structure the network and core data operations. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,避免在 Core Data 中存储大的 blob,保存缩略图就可以了(尽管您应该针对它优化模型),但是在 Documents 文件夹中重建后,您应该存储完整的图像。
您绝对应该使用队列,NSOperationQueue 或 ASI 网络队列。我在我的应用程序中做了类似的事情,它有多个依赖项。因此,对于 30 个对象中的每一个,当下载 15 个图像时,您需要调用一个块(或工作函数)。理想情况下,您希望在主线程之外完成这项工作。将所有这些要求放在一起,我想说您至少需要两个队列,一个用于网络请求,一个用于工作块,并且您应该使用 NSBlockOperations,这使整个事情变得更加容易。所以,代码会是这样的...
然后您还需要编写委托方法,didFinish 看起来像这样...
所有这些都将进入连接到服务器的类中,并且创建你的对象,所以它不是一个视图控制器或任何东西,只是一个常规的 NSObject 子类。它将需要有两个队列、一个托管对象上下文(并且很可能是一个返回另一个 MOC 供您在线程中使用的方法,如下所示:)
您
还需要以某种方式挂钩来监视进度,重新- 排队失败的下载、取消并在最后保存 MOC 重新排队失败的下载非常棘手。
因此,为了澄清,在您的委托方法中,您将下载的图像存储在 a 中。你的临时实例变量然后,当所有 15 个依赖项完成后,您就可以访问该实例变量并完成您的工作。
First of all, avoid storing large blobs in Core Data, saving the thumbnails is fine (although you should optimize your model for it), but you should store the full image once it's reconstructed in the Documents folder.
You should definitely use a queue, either NSOperationQueue or ASI network queue. I do something similar in my app which has multiple dependencies. So, for each of the 30 objects you need to have a block (or work function) get called when the 15 images have downloaded. You ideally want to do this work off the main thread. Put all these requirements together, and I'd say you need at least two queues, one for network requests and one for worker blocks, and you should use NSBlockOperations which makes the whole thing much easier. So, the code would be something like this...
Then you'll also need to write the delegate methods, the didFinish one would look something like this...
And all of that would go into your class which connects to your server and creates your objects, so it's not a view controller or anything, just a regular NSObject subclass. It will need to have two queues, a managed object context (and more than likely a method which returns another MOC for you to use in threads, something like this:
}
You'll also need to hook in some way of monitoring progress, re-queuing failed downloads, cancelling, and saving the MOC at the end. Re-queuing failed downloads is quite tricky. Anyway, hope that helps.
So, just to clarify, in your delegate method, you'd store the downloaded image in a temporary instance variable on your Object. Then when all 15 dependencies finish, you can access that instance variable and do your work.
首先,1 个队列应该足以满足所有图像请求。
您可能想要做的是保留对请求的引用,以便在不再需要该对象时可以取消它们。
对于锁定,图像需要考虑一些事项:
只需使用 3 个不同的 NSOperationQueue 将使您的应用程序响应更快:
1 用于 ASIHTTPRequests(不要创建新的,使用 startAsynchronous 的默认值)
1 用于将图像写入磁盘
1 用于从磁盘获取图像
To kick things off, 1 Queue should be enough for all the image requests.
What you might want to do is keep references to the request so you can cancel them if the object is no longer needed.
For the locking, there's a few things to consider with images:
Just using 3 different NSOperationQueue will make your app much more responsive:
1 for ASIHTTPRequests (Don't create a new one, use the default with startAsynchronous)
1 for image writing to disk
1 for image fetching from disk
既然您将显示图像以供查看,为什么不使用 SDwebImage:
SDImageCache 管理异步下载队列,将下载器与图像缓存存储联系起来,维护内存缓存和可选的磁盘缓存。磁盘缓存写入操作是异步执行的,因此不会给 UI 增加不必要的延迟。
[imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]]
https://github.com/rs/SDWebImage
Since you will display image to view, why don't you SDwebImage:
SDImageCache manages an asynchronous download queue, ties the downloader with the image cache store, maintains a memory cache and an optional disk cache. Disk cache write operations are performed asynchronous so it doesn't add unnecessary latency to the UI.
[imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]]
https://github.com/rs/SDWebImage