skip to Main Content

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.

2

Answers


  1. 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
    
    Login or Signup to reply.
  2. 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.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search