重新安装应用程序后如何从iCloud中的文件获取数据? [英] How to get data from a file in iCloud after reinstalling the app?

查看:90
本文介绍了重新安装应用程序后如何从iCloud中的文件获取数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

应用程序使用iCloud使用NSKeyedArchiver/NSKeyedUnarchiver存储符合Codable协议的对象. 设备之间的同步是可以的,除非将应用程序重新安装在设备上(或安装在新设备上)并且存在带有数据的文件–在这种情况下 NSKeyedUnarchiver.unarchiveObject(withFile:filePathe)返回nil. 当我在新设备上安装应用程序(在同一设备上重新安装)时,如何从iCloud的现有文件中获取数据?

The application uses iCloud to store the objects conformed to Codable protocol using NSKeyedArchiver/NSKeyedUnarchiver. Synchronization between devices is OK, except when the application is reinstalled on the device (or installed on a new device) and the file with data exists – in this case NSKeyedUnarchiver.unarchiveObject(withFile: filePathe) return nil. How to get data from an existing file from the iCloud when I install the application on a new device (reinstall on the same device)?

class ViewController: UIViewController {

@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var weightLabel: UILabel!
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var weightTextField: UITextField!

var iCloudContainer: URL? {
    return FileManager().url(forUbiquityContainerIdentifier: nil)
}

func getFilePath(container: URL, fileName: String) -> String {
    let filePath = container.appendingPathComponent(fileName).path

    return filePath
}

override func viewDidLoad() {
    super.viewDidLoad()
}

@IBAction func fetchButtonPressed(_ sender: UIButton) {

    let container = self.iCloudContainer
    let filePathe = getFilePath(container: container!, fileName: "Person")

    if let jsonData = NSKeyedUnarchiver.unarchiveObject(withFile: filePathe) as? Data {
        if let person = try? JSONDecoder().decode(Person.self, from: jsonData) {
            nameLabel.text = person.name
            weightLabel.text = String(person.weight)
        } else {
            nameLabel.text = "No data loaded"
            weightLabel.text = "No data loaded"
        }
    } else {
        nameLabel.text = "No data loaded"
        weightLabel.text = "No data loaded"
    }

}

@IBAction func saveButtonPressed(_ sender: UIButton) {
    let container = self.iCloudContainer
    let filePathe = getFilePath(container: container!, fileName: "Person")

    let person = Person(name: nameTextField.text!, weight: Double(weightTextField.text!)!)
    let jsonData = try? JSONEncoder().encode(person)
    NSKeyedArchiver.archiveRootObject(jsonData!, toFile: filePathe)
}

推荐答案

要将数据从iCloud容器获取到本地UbiquityContainer,您应该使用NSMetadata在iCloud中查找并将项目下载到设备.

To get data from iCloud container to your local UbiquityContainer you should use NSMetadata to find and download items from iCloud to device.

    lazy var metadataQuery : NSMetadataQuery = {
    let query = NSMetadataQuery()
    query.searchScopes = [NSMetadataQueryUbiquitousDocumentsScope]
    query.predicate = NSPredicate(format: "%K CONTAINS %@", NSMetadataItemFSNameKey, "List")

    NotificationCenter.default.addObserver(self, selector: #selector(didFinishGathering), name: NSNotification.Name.NSMetadataQueryDidUpdate, object: query)
    NotificationCenter.default.addObserver(self, selector: #selector(didFinishGathering), name: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: query)

    return query
}()

override func viewDidLoad() {
    super.viewDidLoad()

    self.metadataQuery.start()

}

    deinit {
        NotificationCenter.default.removeObserver(self)
    }


@objc func didFinishGathering(notification: Notification?) {
    let query = notification?.object as? NSMetadataQuery

    query?.enumerateResults { (item: Any, index: Int, stop: UnsafeMutablePointer<ObjCBool>) in
        let metadataItem = item as! NSMetadataItem

        if isMetadataItemDownloaded(item: metadataItem) == false {

            let url = metadataItem.value(forAttribute: NSMetadataItemURLKey) as! URL

            try? FileManager.default.startDownloadingUbiquitousItem(at: url)
        }
    }

    guard let queryresultsCount = query?.resultCount else { return }
    for index in 0..<queryresultsCount {
        let item = query?.result(at: index) as? NSMetadataItem
        let itemName = item?.value(forAttribute: NSMetadataItemFSNameKey) as! String

        let container = filesCoordinator.iCloudContainer
        let filePath = filesCoordinator.getFilePath(container: container!, fileName: "TaskList")
        let addressPath = filesCoordinator.getFilePath(container: container!, fileName: "CategoryList")

        if itemName == "TaskList" {
            if let jsonData = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as? Data {
                if let person = try? JSONDecoder().decode(Person.self, from: jsonData) {
                    nameLabel.text = person.name
                    weightLabel.text = String(person.weight)
                } else {
                    nameLabel.text = "NOT decoded"
                    weightLabel.text = "NOT decoded"
                }
            } else {
                nameLabel.text = "NOT unarchived"
                weightLabel.text = "NOT unarchived"
            }
        } else if itemName == "CategoryList" {
            if let jsonData = NSKeyedUnarchiver.unarchiveObject(withFile: addressPath) as? Data {
                if let address = try? JSONDecoder().decode(Address.self, from: jsonData) {
                    streetLabel.text = address.street
                    houseLabel.text = String(address.house)
                } else {
                    streetLabel.text = "NOT decoded"
                    houseLabel.text = "NOT decoded"
                }
            } else {
                streetLabel.text = "NOT unarchived"
                houseLabel.text = "NOT unarchived"
            }
        }
    }
}

func isMetadataItemDownloaded(item : NSMetadataItem) -> Bool {
    if item.value(forAttribute: NSMetadataUbiquitousItemDownloadingStatusKey) as? String == NSMetadataUbiquitousItemDownloadingStatusCurrent {
        return true
    } else {
        return false
    }
}


@IBAction func saveButtonPressed(_ sender: UIButton) {
    let container = filesCoordinator.iCloudContainer
    let personPath = filesCoordinator.getFilePath(container: container!, fileName: "TaskList")
    let addressPath = filesCoordinator.getFilePath(container: container!, fileName: "CategoryList")

    let person = Person(name: nameTextField.text!, weight: Double(weightTextField.text!)!)
    let jsonPersonData = try? JSONEncoder().encode(person)
    NSKeyedArchiver.archiveRootObject(jsonPersonData!, toFile: personPath)

    let address = Address(street: streetTextField.text!, house: Int(houseTextField.text!)!)
    let jsonAddressData = try? JSONEncoder().encode(address)
    NSKeyedArchiver.archiveRootObject(jsonAddressData!, toFile: addressPath)
}

}//课程结束

这篇关于重新安装应用程序后如何从iCloud中的文件获取数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆