今回はCloudKitで画像ファイルを連携してみます。
環境:swift 4.2、Xcode 10.1
#RecrodTypeの設定
まずCloudKit DashboardでRecordTypeに画像を保存するフィールドを追加します。
画像はBytes型で保存できます。
あと画像の向き(詳細は後述)を保存する為にInt型のフィールドも用意しておきます。
#画像をCloudKitに保存
画像をCloudKitに保存する時にはUIImage型からNSData型に変換する必要があります。
//UIImageをNSDataに変換
let imageData = image.jpegData(compressionQuality: 1.0)
CloudKitの1レコードあたりのサイズは最大1MB以内という制限があります。
その為、1MBに収まる様にcompressionQuality(圧縮率)を調整する必要があります。
また画像の向き(UIImage.Orientation)をチェックしておきます。
画像の向きが下向きになっている場合はNSData型からUIImage型に戻す時に画像を下向きにするように指定しないと画像の上下が反転してしまう為です。
//UIImageの方向を確認
var imageOrientation:Int = 0
if (image.imageOrientation == UIImage.Orientation.down){
imageOrientation = 2
}else{
imageOrientation = 1
}
こうして取得した画像のデータ(NSData)と画像の向きをCloudKitに保存します。
import CloudKit
---------- (中略) -----------
/**
Cloud KitにデータをINSERTする
@param INSERTするデータ code:コード name:名称 costRate:原価率 salesPrice:売単価 image:画像
*/
private func insertData(code:String,name:String,costRate:Double,salesPrice:Int,image:UIImage!){
let ckDatabase = CKContainer.default().privateCloudDatabase
//INSERTするデータを設定
let ckRecord = CKRecord(recordType: "GoodsMaster")
ckRecord["code"] = code
ckRecord["name"] = name
ckRecord["costRate"] = costRate
ckRecord["salesPrice"] = salesPrice
if (image != nil){
//UIImageをNSDataに変換
let imageData = image.jpegData(compressionQuality: 1.0)
//UIImageの方向を確認
var imageOrientation:Int = 0
if (image.imageOrientation == UIImage.Orientation.down){
imageOrientation = 2
}else{
imageOrientation = 1
}
ckRecord["image"] = imageData
ckRecord["imageOrientation"] = imageOrientation
}
//データのINSERTを実行
ckDatabase.save(ckRecord, completionHandler: { (ckRecords, error) in
if error != nil {
//INSERTがエラーになった場合
print("\(String(describing: error?.localizedDescription))")
}
})
}
#画像をCloudKitから検索
では次にCloudKitに保存した画像を検索してみます。
import CloudKit
---------- (中略) -----------
private let tableView:UITableView = UITableView()
private var goodsMasters:[GoodsMaster] = [GoodsMaster]()
struct GoodsMaster {
var code:String
var name:String
var costPrice:Double
var salesPrice:Int
var image:UIImage!
}
---------- (中略) -----------
/**
Cloud Kitからデータを検索する
@param 検索条件 minSalesPrice:検索条件のsalesPriceの最小値 maxSalesPrice:検索条件のsalesPriceの最大値
*/
private func searchData(minSalesPrice:Int,maxSalesPrice:Int){
let ckDatabase = CKContainer.default().privateCloudDatabase
//検索条件指定
let ckQuery = CKQuery(recordType: "GoodsMaster", predicate: NSPredicate(format: "salesPrice >= %d and salesPrice <= %d", argumentArray: [minSalesPrice,maxSalesPrice]))
//ソート条件指定
ckQuery.sortDescriptors = [NSSortDescriptor(key: "salesPrice", ascending: false),NSSortDescriptor(key: "costRate", ascending: true)]
//検索実行
ckDatabase.perform(ckQuery, inZoneWith: nil, completionHandler: { (ckRecords, error) in
if error != nil {
//検索エラー
print("\(String(describing: error?.localizedDescription))")
}else{
//検索成功
self.goodsMasters.removeAll()
for ckRecord in ckRecords!{
var image:UIImage! = nil
if (ckRecord["image"] != nil){
image = UIImage(data: ckRecord["image"]!)
let imageOrientation:Int = ckRecord["imageOrientation"]!
if (imageOrientation == 2) {
image = UIImage(cgImage: image!.cgImage!, scale: image!.scale, orientation: UIImage.Orientation.down)
}
}
let goodsMaster = GoodsMaster(code: ckRecord["code"]!, name: ckRecord["name"]!, costPrice: ckRecord["costRate"]!, salesPrice: ckRecord["salesPrice"]!,image:image)
self.goodsMasters.append(goodsMaster)
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
})
}
検索して取得したNSData型をUIImage型に変換します。
if (ckRecord["image"] != nil){
image = UIImage(data: imageData!)
---------- (中略) ----------
}
画像の向きが下向きだった時は以下の様に画像を下向きに変換します。
前述の様にこれを行わないと画像の上下が反転してしまいます。
let imageOrientation:Int = ckRecord["imageOrientation"]!
if (imageOrientation == 2) {
image = UIImage(cgImage: image!.cgImage!, scale: image!.scale, orientation: UIImage.Orientation.down)
}
いかがでしたか。
圧縮してNSDataに変換して保存しているので、iCloud Documentsに画像ファイルのまま保存するより効率がいいと思います。
#GitHub
今回紹介したサンプルコードはGitHubで公開しています。
#参考文献
Creating a Database Schema by Saving Records - Apple Developer
CloudKitを使ってみた Swift4版 - Qiita