7

I am using a slightly updated code of this question: Method for downloading iCloud files? Very confusing?

Here is an excerpt of the code:

private func downloadUbiquitiousItem(atURL url: URL) -> Void {
        do {
            try FileManager.default.startDownloadingUbiquitousItem(at: url)
            do {
                let attributes = try url.resourceValues(forKeys: [URLResourceKey.ubiquitousItemDownloadingStatusKey])
                if let status: URLUbiquitousItemDownloadingStatus = attributes.allValues[URLResourceKey.ubiquitousItemDownloadingStatusKey] as? URLUbiquitousItemDownloadingStatus {
                    if status == URLUbiquitousItemDownloadingStatus.current {
                        self.processDocument(withURL: url)
                        return
                    } else if status == URLUbiquitousItemDownloadingStatus.downloaded {
                        self.processDocument(withURL: url)
                        return
                    } else if status == URLUbiquitousItemDownloadingStatus.notDownloaded {
                        do {
                            //will go just fine, if it is unnecessary to download again
                            try FileManager.default.startDownloadingUbiquitousItem(at: url)
                        } catch {
                            return
                        }
                    }
                }
            } catch {

            }

            //only happens if the try does not fail
            self.documentsQuery = NSMetadataQuery()
            self.documentsQuery.searchScopes = [NSMetadataQueryUbiquitousDocumentsScope]
            self.documentsQuery.valueListAttributes = [NSMetadataUbiquitousItemPercentDownloadedKey,NSMetadataUbiquitousItemDownloadingStatusKey]
            self.documentsQuery.predicate = NSPredicate(format: "%K like 'backup.json'", argumentArray: [NSMetadataItemFSNameKey])

            NotificationCenter.default.addObserver(self, selector: #selector(self.queryUpdate(notification:)), name: NSNotification.Name.NSMetadataQueryDidUpdate, object: self.documentsQuery)

            DispatchQueue.main.async {
                if self.documentsQuery.start() {
                    if self.restoreHUD != nil {
                        self.restoreHUD.show(animated: true)
                        //timeout for restoring
                        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(30), execute: { 
                            if self.restoreHUD != nil {
                                self.restoreHUD.hide(animated: true)
                            }
                        })
                    }
                }
            }
        } catch {
            //file does not exist in icloud most likely
        }
    }

So this works sometimes, but it is really unstable, for example we tested the following cases:

  1. Backup to iCloud
  2. Check that we have a valid document in Settings -> iCloud -> Storage -> Manage Storage -> MyApp -> backup.json
  3. Force a first launch, so that the app restores backup.json (aka executes the code above)

This sometimes works and sometimes doesn't. Sometimes the query won't update.

We also tested the following scenario:

  1. Remove backup from iCloud manually via settings
  2. Uninstall the app and reinstall it to provide a first launch
  3. the startDownloadingUbiquitousItem function does not seem to throw, even though nothing is in iCloud because I think that iCloud still hasn't synced the local file or deleted the local data, but it also does not download properly... yet the status is notDownloaded.

Maybe users are not supposed to wipe the stuff via Settings? I'd like to know if my code is missing a case that could happen, or if this API is just really unhandy for developers...

Thanks!

Community
  • 1
  • 1
Janosch Hübner
  • 1,584
  • 25
  • 44

1 Answers1

0

Probably, we call to adding notification in "main thread".

NotificationCenter.default.addObserver(self, selector: #selector(self.queryUpdate(notification:)), name: NSNotification.Name.NSMetadataQueryDidUpdate, object: self.documentsQuery)
ken555
  • 1