SWIFT - 将文件上传到 icloud 文档未完成
Posted
技术标签:
【中文标题】SWIFT - 将文件上传到 icloud 文档未完成【英文标题】:SWIFT - Uploading file to icloud documents does not finish 【发布时间】: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)
【问题讨论】:
【参考方案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上的文件应用程序中的文件夹名称。以上是关于SWIFT - 将文件上传到 icloud 文档未完成的主要内容,如果未能解决你的问题,请参考以下文章
编程有点新 - 将大量与编程相关的文件上传到 iCloud [关闭]
如何在 Swift 中以编程方式打开 icloud 应用程序(文件)