5

I am caching CKRecord on client and fileUrl of CKAsset too. Can fileUrl change from time to time? Asset / data itself is not changing.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
János
  • 32,867
  • 38
  • 193
  • 353

2 Answers2

7

The fileURL of an asset will not change, but if this is an asset you downloaded from the server the data is only guaranteed to exist at that location until the completion block of the operation is called. After that point the asset's backing file may be cleaned up at any time to free up disk space.

After downloading an asset from the server you should move or copy the backing file to another location in your application's container if you'd like to keep it.

farktronix
  • 3,880
  • 1
  • 21
  • 27
  • I guess you are wrong, the same record is downloaded two times, its asset `fileUrl` **first** is: `file:///private/var/mobile/Containers/Data/Application/A59350D5-29A7-4449-9EC4-BD7AC9DFE24C/Library/Caches/CloudKit/Assets/A9A42324-769C-4EB6-B4AD-84AD3786DE38.01c9e1814d5722086f36c96607aaba3dc758ee65f7` **second**: `file:///private/var/mobile/Containers/Data/Application/A59350D5-29A7-4449-9EC4-BD7AC9DFE24C/Library/Caches/CloudKit/Assets/1AF74DED-A10E-4C64-BB62-E7B69C0E04F6.01c9e1814d5722086f36c96607aaba3dc758ee65f7` – János Apr 28 '15 at 18:12
  • before the "." there is a difference. Should I use the part after the "." in the last path component? Behave that like a crc? – János Apr 28 '15 at 18:13
  • 1
    To clarify my comment above, the `fileURL` property of a `CKAsset` in memory will not change. Every time you download a `CKAsset` from the server you get a new `CKAsset` instance and it may have a different `fileURL`. You should make no assumptions about the format of the `fileURL` string. – farktronix Apr 28 '15 at 19:43
  • I built this to solve a bunch of this. Hope it helps someone. This framework handles everything. From download to cache and all you need is the recordID and the property key of your asset. You use the methods directly on the imageview. Hope this helps. Feel free to help improve it. https://github.com/agibson73/AGCKImage – agibson007 Mar 22 '16 at 13:29
  • Any reason I couldn't hard link the file instead of copying? Also, it seems like moving would be a bad idea since CloudKit might still try to use it. Might even try re-downloading if it's gone. I'm going to try linking and I'll report back if I run into a problem. (If it works it would be way more efficient and almost zero risk of running out of space) – garafajon Oct 05 '16 at 16:27
0

The archived URL is a full path, but since iOS 8 or so the container URL that your app uses to store its files changes everytime the app starts.

So the archived URL is wrong.

This seems like a bug in the way CKAssets are archived to me, they should be archiving and unarchiving the partial path relative to the app's container. Not the full path.

I guess I'll file a radar.

Edit: here's a solution:

extension CKAsset {
    var url: URL? {
        let path = fileURL.path
        if FileManager.default.fileExists(atPath: path) {
            return fileURL
        } else if let index = path.range(of: "/Library/Caches/") {

            // archived CKAssets store full-path URLs but since iOS 8 or so
            // the path of our container (home-dir) changes every time we are
            // started. So the full path is useless. Try to mangle it.

            let suffix = String(path.suffix(from: index.upperBound))
            let adjustedUrl = URL.caches/suffix
            if FileManager.default.fileExists(atPath: adjustedUrl.path) {
                return adjustedUrl
            }
        }
        return nil
    }
}

public extension URL {
    static var caches: URL {
        return FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first ?? URL(fileURLWithPath: "")
    }
}
mxcl
  • 26,392
  • 12
  • 99
  • 98