Home > other >  What is the best strategy for saving a "Most Recently Used" document list on iOS?
What is the best strategy for saving a "Most Recently Used" document list on iOS?

Time:11-10

Is there a foolproof way of saving the URL of a UIDocument so an application can resume editing the document on next launch?

I have tried various ways of saving the URL, but sometimes the document URL will slightly differ from what is expected.

For example, the following code:

var scoresURL = FileManager.default.urls(for: .documentDirectory,
                                             in: .userDomainMask).first!

might return this:

file:///var/mobile/Containers/Data/Application/50E947C1-7A30-40A0-8BB6-1C3BB41A1218/Documents  

But a documented loaded using UIDocumentBrowserViewController might set the fileURL path of the UIDocument to this:

file:///private/var/mobile/Containers/Data/Application/50E947C1-7A30-40A0-8BB6-1C3BB41A1218/Documents  

It is these slight differences that make me wonder if I am simply doing the wrong thing by maintaining a MRU list.

These issues appear only on an actual device. The simulator is paths are stable, at least until the arbitrary times the simulator decides to reset its state.

CodePudding user response:

You could check which one is the last modified one:

var scoresURL = FileManager.default.urls(for: .documentDirectory,
                                             in: .userDomainMask)

let modificationDatesAndURL: (Date, URL) = scoresURL.compactMap { filePathURL in
    let attributes = FileManager.default.attributesOfItem(atPath: urlPath.path)
    if let modificationDate = attributes?[.modificationDate] as? Date {
        return (modificationDate, filePathURL)
    } else {
        return nil
    }
    
}

/// Sort tuples by date
let lastModifiedScoreDateAndURL = modificationDatesAndURL.sorted(by: { $0.0 < $1.0 }).first
let lastModifiedURL = lastModifiedScoreDateAndURL.1

CodePudding user response:

I think that bookmarkData is what you may be looking for. The docs don't say much but the general idea is that you persist the bookmark data using this method

func bookmarkData(
    options: URL.BookmarkCreationOptions = [],
    includingResourceValuesForKeys keys: Set<URLResourceKey>? = nil,
    relativeTo url: URL? = nil
) throws -> Data

and then recreate the URL using this initializer:

init(
    resolvingBookmarkData data: Data,
    options: URL.BookmarkResolutionOptions = [],
    relativeTo url: URL? = nil,
    bookmarkDataIsStale: inout Bool
) throws

Personally I haven't run into any issues with it, since I'm referencing directories rather than single files, but found cautionary articles (like this one) - to quote its conclusion :

Rules of URL bookmarks

  • Always check if bookmark data is stale (bookmarkDataIsStale)
  • if data is stale, update ALL bookmark data - including all the bookmarks possibly stored elsewhere.
  • be careful with atomic updates - need discipline to not use it.
  • If need persistence and atomic writes better use something else - updating stored bookmark after every save is cumbersome and error prone.
  • Related