CloudKitのデータをCSVにExportする方法(Swift5)
iOS アプリを開発するときに、データの格納先としてCloudKit を選択することは多いのではないだろうか。CloudKit はiCloud 上のデータベースで、アプリ単位1PB まで利用できる。
CloudKit Dashboard という管理機能も備え、スキーマやレコードの管理もでき非常に便利なのだが、一つ大きな欠点がある。
CloudKit Dashboard からデータをエクスポートできない
報告や分析するときにデータをエクスポートして加工することは多いのではないだろうか。残念ながらCloudKit Dashboard 上では、そこまでグラフィカルな表現はできず、またデータのエクスポート機能も備えていない。
そこで今回はSwift5 でCloudKit のデータをCSV にExport する方法を書く。
Swift5 でCloudKit のデータをCSV にExport する
ソースコード
private func exportCloudKit(){ let df = DateFormatter() df.dateFormat = "yyyy-MM-dd HH:mm:ss" // Change header var text = "Created,Code,Name\n"; cloudKitLoadRecords() { (records, error) -> Void in if let error = error { print(error) } else { if let records = records { for record in records{ // Change Fields let date = record.creationDate != nil ? df.string(from: record.creationDate!) : "" let code = record["code"] as! String let name = record["name"] != nil ? record["name"] as! String : "" text += date + "," + code + "," + name + "," + "\n" } } let dir = FileManager.default.urls( for: .documentDirectory, in: .userDomainMask ).first! let fileUrl = dir.appendingPathComponent("CloudKitExport.csv") if FileManager.default.createFile( atPath: fileUrl.path, contents: text.data(using: .utf8), attributes: nil ) { } else { print("Failed to create file") } print("Processed") } } } func cloudKitLoadRecords(result: @escaping (_ objects: [CKRecord]?, _ error: Error?) -> Void) { // Change recordType let cloudKitQuery = CKQuery(recordType: "Sample", predicate: NSPredicate(value: true)) var records = [CKRecord]() // If you use Private Database, Chage here 'CKContainer.default().privateCloudDatabase' let database = CKContainer.default().publicCloudDatabase var recurrentOperationsCounter = 101 func recurrentOperations(cursor: CKQueryOperation.Cursor?){ let recurrentOperation = CKQueryOperation(cursor: cursor!) recurrentOperation.recordFetchedBlock = { (record:CKRecord!) -> Void in recurrentOperationsCounter += 1 records.append(record) } recurrentOperation.queryCompletionBlock = { (cursor: CKQueryOperation.Cursor?, error: Error?) -> Void in if ((error) != nil) { print(String(describing: error)) result(nil, error) } else { if cursor != nil { recurrentOperations(cursor: cursor!) } else { result(records, nil) } } } database.add(recurrentOperation) } var initialOperationCounter = 1 let initialOperation = CKQueryOperation(query: cloudKitQuery) initialOperation.recordFetchedBlock = { (record:CKRecord!) -> Void in initialOperationCounter += 1 records.append(record) } initialOperation.queryCompletionBlock = { (cursor: CKQueryOperation.Cursor?, error: Error?) -> Void in if ((error) != nil) { print(String(describing: error)) result(nil, error) } else { if cursor != nil { recurrentOperations(cursor: cursor!) } else { result(records, nil) } } } database.add(initialOperation) }
使い方
今回の例では手間を省くためXCode のApp デフォルトで作成されるものをベースに、ContentView.swift に↑のfunc を置いてbody を以下のように変更した。
var body: some View { List { } .toolbar { Button(action: exportCloudKit) { Label("export", systemImage: "square.and.arrow.down") } } }
右上のボタンを押すとCSV を出力する。
CSV の出力先は、ユーザ名\ライブラリ\Containers\ツール名\Data\Documents になるので、場所がわからないときはファイル名(CloudKitExport.csv)で検索する。
使うときに変更する箇所
CSV のヘッダ。今回はCreated, Code, Name の3つを出力している
// Change header var text = "Created,Code,Name\n";
出力したいフィールド。値がない可能性があるフィールドは、name のようにnilチェックする
// Change Fields let date = record.creationDate != nil ? df.string(from: record.creationDate!) : "" let code = record["code"] as! String let name = record["name"] != nil ? record["name"] as! String : "" text += date + "," + code + "," + name + "," + "\n"
出力したいRecordType。
// Change recordType let cloudKitQuery = CKQuery(recordType: "Sample", predicate: NSPredicate(value: true))
データベースがPublic かPrivate か
// If you use Private Database, Chage here 'CKContainer.default().privateCloudDatabase' let database = CKContainer.default().publicCloudDatabase
設定方法は後述するが、Production かDevelopment か
ハマったポイント
100レコードまでしか出力されない
最初はperformQuery を使っていたが、100レコードまでしか出力されなかった。CKQueryOperation を使って回す必要があった。
デバッグ実行でProduction からデータを出力したい
特に設定しない場合は、Development からデータが出力された。以下の設定をすることでProduction から出力できた。
- entitlements を開く
- +ボタンを押して、com.apple.developer.icloud-container-environment のキーを追加する
- Type をString 、Value をProduction に設定する。
コメント
コメントを投稿