Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
1
Help us understand the problem. What is going on with this article?
@NaoSekig

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で公開しています。

参考文献

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

関連記事

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

1
Help us understand the problem. What is going on with this article?
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
NaoSekig
Studio K's オーナープログラマー。 自社アプリ開発と請負開発の二足のわらじで奮闘中です(^o^)。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
1
Help us understand the problem. What is going on with this article?