【问题标题】:SWIFT - Uploading file to icloud documents does not finishSWIFT - 将文件上传到 icloud 文档未完成
【发布时间】:2020-01-25 03:24:03
【问题描述】:

我使用了下面页面上的教程,由于某种原因,文件开始上传并在控制台上显示为 95%,但从未显示“备份上传完成”的消息。该应用仅用于测试sample.mp4文件的上传。

https://medium.com/swlh/backup-your-applications-data-with-icloud-and-track-progress-48a00ebd2891

//  BackupToIcloudController.swift


import Foundation

import UIKit

class BackupToIcloudController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = UIButton(frame: CGRect(x: UIScreen.main.bounds.midX - 150, y: UIScreen.main.bounds.midY - 20, width: 300, height: 40))
        button.setTitle("Upload to iCloud", for: .normal)
        button.addTarget(self, action: #selector(self.uploadToCloud), for: .touchUpInside)
        button.backgroundColor = .blue
        view.addSubview(button)
    }

    @objc func uploadToCloud() {
        let backup = Backup.init()
        try? backup.startBackup()
    }

    @IBAction func back(_ sender: Any) {
        self.dismiss(animated: true, completion: nil)
    }
}
//  Backup.swift


import Foundation

class Backup: NSObject {

   var query: NSMetadataQuery!

   override init() {
        super.init()
        initialiseQuery()
        addNotificationObservers()
    }
    func initialiseQuery() {

        query = NSMetadataQuery.init()
        query.operationQueue = .main
        query.searchScopes = [NSMetadataQueryUbiquitousDataScope]
        query.predicate = NSPredicate(format: "%K LIKE %@", NSMetadataItemFSNameKey, "sample.mp4")
    }

    func startBackup() throws {
        guard let fileURL = Bundle.main.url(forResource: "sample", withExtension: "mp4") else {
            return

        }
        guard let containerURL = FileManager.default.url(forUbiquityContainerIdentifier: "iCloud.mylojastore.com.backup") else { return }

        if !FileManager.default.fileExists(atPath: containerURL.path) {
            try FileManager.default.createDirectory(at: containerURL, withIntermediateDirectories: true, attributes: nil)
        }
        let backupFileURL = containerURL.appendingPathComponent("sample.mp4")
        if FileManager.default.fileExists(atPath: backupFileURL.path) {
           try FileManager.default.removeItem(at: backupFileURL)
            try FileManager.default.copyItem(at: fileURL, to: backupFileURL)
        } else {
            try FileManager.default.copyItem(at: fileURL, to: backupFileURL)
        }

        query.operationQueue?.addOperation({ [weak self] in
            _ = self?.query.start()
            self?.query.enableUpdates()
        })
    }
    func addNotificationObservers() {

        NotificationCenter.default.addObserver(forName: NSNotification.Name.NSMetadataQueryDidStartGathering, object: query, queue: query.operationQueue) { (notification) in
            self.processCloudFiles()
        }

        NotificationCenter.default.addObserver(forName: NSNotification.Name.NSMetadataQueryDidUpdate, object: query, queue: query.operationQueue) { (notification) in
            self.processCloudFiles()
        }
        NotificationCenter.default.addObserver(forName: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: query, queue: query.operationQueue) { (notification) in
            self.processCloudFiles()
        }
        NotificationCenter.default.addObserver(forName: NSNotification.Name.NSMetadataQueryGatheringProgress, object: query, queue: query.operationQueue) { (notification) in
                  print("progress")
               }
    }

    @objc func processCloudFiles() {

        if query.results.count == 0 { return }
        var fileItem: NSMetadataItem?
        var fileURL: URL?

        for item in query.results {

            guard let item = item as? NSMetadataItem else { continue }
            guard let fileItemURL = item.value(forAttribute: NSMetadataItemURLKey) as? URL else { continue }
            if fileItemURL.lastPathComponent.contains("sample.mp4") {
                fileItem = item
                fileURL = fileItemURL
            }
        }

        let fileValues = try? fileURL!.resourceValues(forKeys: [URLResourceKey.ubiquitousItemIsUploadingKey])
        if let fileUploaded = fileItem?.value(forAttribute: NSMetadataUbiquitousItemIsUploadedKey) as? Bool, fileUploaded == true, fileValues?.ubiquitousItemIsUploading == false {
            print("backup upload complete")

        } else if let error = fileValues?.ubiquitousItemUploadingError {
            print("upload error---", error.localizedDescription)

        } else {
            if let fileProgress = fileItem?.value(forAttribute: NSMetadataUbiquitousItemPercentUploadedKey) as? Double {
                print("uploaded percent ---", fileProgress)
            }
        }
    }
}

【问题讨论】:

    标签: ios swift icloud


    【解决方案1】:

    看来我们必须在 plist 中指定容器才能使其工作。

    将以下内容添加到您的 plist 中。

    <key>NSUbiquitousContainers</key>
    <dict>
        <key>iCloud.iCloudBackup</key>
        <dict>
            <key>NSUbiquitousContainerIsDocumentScopePublic</key>
            <true/>
            <key>NSUbiquitousContainerName</key>
            <string>iCloudBackup</string>
            <key>NSUbiquitousContainerSupportedFolderLevels</key>
            <string>Any</string>
        </dict>
    </dict>
    

    你应该看到这个。

    【讨论】:

    • 直到今天我仍然无法解决这个问题......你提到的我已经提出......有时它可以工作,有时它会继续出现这个问题。它们没有交替,它工作了好几次,突然它开始几次超过 95%,然后又工作了。我什至暂时把我的应用程序的这个功能放在一边,但我真的需要一个解决方案。
    • NSUbiquitousContainerName 参数中输入的名称应该在哪里使用?我从来没有发现这个名字的用途
    • 它将被用作Mac上iCloud驱动器文件夹中的文件夹名称,或iOS上的文件应用程序中的文件夹名称。
    猜你喜欢
    • 2013-08-04
    • 2012-12-20
    • 2013-04-17
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    • 2015-11-24
    • 2018-04-08
    • 1970-01-01
    相关资源
    最近更新 更多