【问题标题】:How to get data from a file in iCloud after reinstalling the app?重新安装应用程序后如何从 iCloud 中的文件中获取数据?
【发布时间】:2019-01-21 10:52:11
【问题描述】:

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

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)
}

【问题讨论】:

    标签: ios swift icloud


    【解决方案1】:

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

        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)
    }
    

    }//课程结束

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-10
      • 2012-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多