We've recently converted our code to use UIDocument instead of manipulating files on the file system directly, and we've encountered some performance issues as a result. We are wondering whether we are using this class incorrectly, if anyone else had these issues, and what are the common ways to address them.
We have a "shoebox app" that manages a bunch of documents, each consisting of multiple image files that can be quite heavy, a small metadata file and a small preview image. The user may have many documents on her device (1000+ documents). Each document's files are grouped in an directory and we use NSFileWrapper to read and write them.
When our app starts, it needs the metadata of all the documents in order to show a document index, and a subset of the preview images. More preview images are loaded as the user scrolls.
In order to get that information, we open all the documents, read their metadata and preview image if we need to, close them, and then open again on demand.
It takes a lot of time to open all the documents and read their metadata. I think there are several factors contributing to this problem: - Each document open action is relatively slow - The open document blocks and the completion blocks are executed on the same queue, which makes the operation's latency very bad (my document is open, but the completion block has to wait for X open document blocks before it can run)
We thought about solving this problem using a separate index file, but this approach has the drawback that we will need to manage the metadata in two places and that we will need to keep it synched with the file system in case iCloud changes the files.
Each open document creates its own "File Access Thread". When we open many documents concurrently, the overhead crushes the app.
We solved this issue by synching the open operations using a semaphore. This approach has the drawback that it slows down the loading even more.
Thanks!
Ok, no good news here.
We tried consulting with friends in the industry, profiling UIDocument and using modified implementations of it that alter various aspects of its operation in order to see if we can improve its performance but to no avail.
My conclusion is that UIDocument is not suitable for this kind of usage - it is just not designed to support the latency and throughput requirements we have for open operations. UIDocument should only be used when you want to open a small number of files at any given moment (much like word processors and drawing apps). Admittedly, this is exactly what Apple's documentation says, but I guess we had to learn just how serious they were the hard way :)
We ended up using some "tricks" to improve the user experience, and will move away from UIDocument as soon as we can.
So my recommendation is that only if:
then use it. Otherwise consider other solutions.
A a side note which is not directly related to the question but I will add here as a public service: UIDocument's async model required some major changes in the app architecture when we moved from direct file access. If you plan on making this move, evaluate the work you will need to do carefully.
Good luck future programmers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With