如何将数据远程加载到 Cloudkit

How to load data into Cloudkit remotely

我构建了一个利用 Apple 的 Cloudkit 功能的应用程序。我觉得困难的是新的笨拙的 Couldkit UI。这使得加载大量数据甚至修改现有记录变得困难。是否可以通过其他方法将数据加载到 Cloudkit 中?例如,有没有一种方法可以将记录的 CSV 文件加载到 Cloudkit?

我使用 FileMaker 数据库中的记录为我的一个应用程序播种(并更新)一个 CloudKit 容器。我的数据源是 .tab 文件而不是 .csv,但它的工作原理是一样的。对于我的项目,我有一个 Artist class.

首先,将 .csv 文件添加到您的 Xcode 项目。

然后您需要将其分成 return 分隔的行数组 data.components(separatedBy: "\r")

该数组中的每一行都需要用 data.components(separatedBy: ",") 分开。我的源文件通常包含逗号,所以我喜欢使用制表符 ("\t") 将它们分开。

// [Artist]
func makeArtistArray(_ fileName: String) -> [Artist] {

    var array = [Artist]()

    do {
        let path = Bundle.main.path(forResource: fileName, ofType: nil)
        let data = try String(contentsOfFile: path!, encoding: String.Encoding.utf8)
        let rows = data.components(separatedBy: "\r")

        // rows.removeAtIndex(0) // if first row contains field names

        for row in rows {

            let values = row.components(separatedBy: "\t")

            let artist = Artist()

            artist.auctionGroup     = values[0] as CKRecordValue
            artist.auctionNumber    = Int(values[1])
            artist.auctionOrder     = Int(values[2])...

            array.append(artist)
        }

    } catch {
        print(error)
    }

    return array
}

然后,我将该数组传递给创建 [CKRecord] 数组并将所有内容保存到容器的 public 数据库的函数。如果您提前知道您的 CKRecordID,您可以使用它来修改现有记录。如果您传递一个不存在的 CKRecordID(或完全忽略它),您将创建一个新记录:

// [CKRecord]
func makeCloudRecords(_ array: [Artist], recordType: String) {

    var records = [CKRecord]()

    for artist in array {

        let recordID  = CKRecordID(recordName: "\(artist.name!) - Artist")            
        let record    = CKRecord(recordType: recordType, recordID: recordID)

        record["auctionGroup"]   = artist.auctionGroup
        record["auctionNumber"]  = artist.auctionNumber as NSNumber?
        record["auctionOrder"]   = artist.auctionOrder as NSNumber?...

        records.append(record)
    }

    // operation
    let operation = CKModifyRecordsOperation(recordsToSave: records, recordIDsToDelete: nil)
    operation.savePolicy = .allKeys

    operation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, operationError in

        if let error = operationError {
            // error
        }

        if let saved = savedRecords {
            // print artist.name, or count the array, or whatever..                
        }
    }

    database.add(operation)
}

然后,最后,在您的应用中设置一个调用 makeArtistArray() 的按钮并将结果传递给 makeCloudRecords()

学习如何(当时)进行了多次试验和错误,没有官方文档。但我已经成功使用这些功能一年多了,定期使用 2 个生产应用程序。希望这能让你朝着正确的方向前进。

*提醒.. 对 components(separatedBy:) 的调用会产生一个字符串数组,因此请注意转换非字符串值,否则您的容器的记录模式将不满意。