Help us understand the problem. What is going on with this article?

CloudKitで画像を連携する

今回はCloudKitで画像ファイルを連携してみます。

環境:swift 4.2、Xcode 10.1

RecrodTypeの設定

まずCloudKit DashboardでRecordTypeに画像を保存するフィールドを追加します。
画像はBytes型で保存できます。
あと画像の向き(詳細は後述)を保存する為にInt型のフィールドも用意しておきます。
スクリーンショット 2019-02-22 21.41.12.png

画像を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に保存します。

ViewController.swift
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に保存した画像を検索してみます。

ViewController.swift
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で公開しています。
https://github.com/naosekig/CloudKitSample

参考文献

Creating a Database Schema by Saving Records - Apple Developer
CloudKitを使ってみた Swift4版 - Qiita

関連記事

CloudKitを使ってみた Swift4版
CloudKitで画像を連携する - CKAsset編

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした