UIDocumentBrowserViewController and External Storage

Some time ago I’ve ported the old and ancient strategy game „Empire“ from macOS to iOS. On macOS I decided to make the game document based. Since the game may last many hours (or even more), it is necessary to store the state of the game in some kind of document to continue it in a later session. On start-up of the game it tries to re-open the last used document. That’s quite easy with the recentDocumentURLs array of the NSDocumentController.

But for iOS such a facility is missing. There is no such thing as a „UIDocumentController“ and the UIDocumentBrowserViewController tells you nothing about recently opened or created documents. I wanted to make the iOS version of Empire document based as well to enable anytime switches between the iOS and macOS version of the game. That’s especially interesting, if the game document is stored on some external server (like iCloud).

Well, that can’t be too difficult, I thought. Since some time it’s possible to develop document based apps for iOS and with the aforementioned UIDocumentBrowserViewController you have the grounds to create or pick documents to open in your app. I tried the following:

  • On creation or on open an existing document I stored the URL supplied from the methods of the UIDocumentBrowserViewController in the user defaults.
  • On start-up of the app I looked if the user defaults for the last opened document were present.
  • If they are, I looked if the stored URL was still reachable.
  • If yes, I opened that document; otherwise I presented the document browser to open or create a new game.

That worked fine for locally stored documents but failed for documents stored on some cloud service (e.g. iCLoud, DropBox, ownCLoud/NextCLoud). The file system manager always told me that the resource was unreachable although the browser showed that the document was still there. Via the document browser I could open the document on the external storage without problems.

If nothing helps ask stackoverflow.com. So I did (https://stackoverflow.com/questions/56324045/how-to-reopen-a-uidocument-on-icloud-using-uidocumentbrowserviewcontroller). The solution works with bookmarks. Instead of storing the url of the last opened document directly I first make a bookmark from it.

As an example this listing shows the callback of the UIDocumentBrowserViewController for document creation. To save the supplied url in the user defaults I signal the system that I am going to access a security scoped resource first. This is necessary if the url points to an external storage; otherwise the creation of the bookmark would fail. If the creation of the bookmark succeeds I store it in the user defaults.

On start-up I do the following:

In the viewDidLoad I look for the user defaults of the last opened document. If it’s there I try to convert it to a url and look if the file is still reachable. If everything’s ok I open that document; otherwise I present the document browser. Funny enough, here I do not need to enclose the access to the url in the pair url.startAccessingSecurityScopedResource() / url.stopAccessingSecurityScopedResource().

Btw, the promise that the bookmark stays valid if the document is moved or renamed seems to be broken on iOS.

Ein Gedanke zu „UIDocumentBrowserViewController and External Storage

  • 25. März 2020 um 11:40
    Permalink

    Wow cuz this is excellent work! Congrats and keep it up.

    Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.