swift CoreData 保存 カメラで取得した画像

まずカメラの利用には

UIImagePickerController

が必要。何をするかというとアップルのサイトより

ユーザーのメディアライブラリから画像を撮影し、ムービーを記録し、アイテムを選択するためのシステムインタフェースを管理するビューコントローラ。
のは、(メディアキャプチャをサポートするデバイス上で)新しい画像やムービーを撮るためのユーザインタフェースを提供します。

ふむふむ、大切ですね。カメラや、動画、写真へのアクセスする際にはこのメッソドを利用します。

クラスはUINavigationControllerDelegateとUIImagePickerControllerDelegateを継承します。

UIViewController , UINavigationControllerDelegate, UIImagePickerControllerDelegate {
sourceTypeUIImagePickerController.SourceType.camera

//関数定義をみるとゲッタセッタをセットするとあります。
var sourceType: UIImagePickerController.SourceType { get set }

UIImagePickerController.SourceType には3つある

case photoLibrary //iphoneの写真から取り込む

case camera //カメラから取り込む

case savedPhotoAlubm //デバイスがカメラ持っていない時のフォトアルバム

表示するときはpresentメソッドを利用する これはuiviewControllerのインスタンスメソッド

func present(_ viewControllerToPresent: UIViewController, 
    animated flag: Bool, 
    completion: (() -> Void)? = nil)

ここではimagePickerControllerを指定しているが、他のクラスも指定できます

// (1)撮影が終わったときに呼ばれるdelegateメソッド

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

        // (2)撮影した写真を、配置したpictureImageに渡す
        pictureImage.image = info[UIImagePickerControllerOriginalImage] as? UIImage

        // (3)モーダルビューを閉じる
        dismiss(animated: true, completion: nil)
    }
}

このデリゲートメソッドはinfo: [String : Any])にカメラで撮影された情報が格納されているとある。 どういう意味かというと、関数定義では

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info;

// info dictionary keys

public let UIImagePickerControllerOriginalImage: String // a UIImage

フレームワークの中では、辞書型 string とidで持っている

info: [String : Any]

のなかで辞書型のデータを渡している。辞書型とはkeyと値のペアで情報を持つ、配列だと思えば良い。 Rubyのハッシュですね。 辞書にアクセスるるのはkeyでアクセスする。 定義を見ると

UIImagePickerControllerOriginalImage: String 

とある。つまり文字列のkeyを渡しているのだ。値は、iphoneのカメラで撮られたデータが入っている。そこから先はは知らなくていい。 目的達成のために、写真が利用できればいいのだ。

あとは保存処理。上記デリゲートメソッドの中の

pictureImage.image = info[UIImagePickerControllerOriginalImage] as? UIImageのあとに書いていこう

        //jpegデータに変換するメソッド 第1引数は画像、第二引数は解像度
        let img = UIImageJPEGRepresentation(pictureImage.image!, 1)
        //save関数に保存は委ねる
        saveData(imageData: img!)

    func saveData(imageData:Data){
       //persistcontainerを作る。入れ物を用意しておく
        let appdelegate = UIApplication.shared.delegate as! AppDelegate
        let context = appdelegate.persistentContainer.viewContext

        //ここポイントです。Photoテーブルの型でpersistcontainerでもってオブジェクトをつくる.
        let photo_core = Photo(context: context)  

        //そうするとphotoテーブルのプロパティ(カラム)にアクセスできる。
        photo_core.pic = imageData

        //エラー処理 後述します。
        do{
            try context.save()
        } catch    {
         print(error)
            }
            
    }

Photoはcoredataのテーブルのことです。

ちなみにcoredataのテーブルのカラムの型は BinaryData型になります。 f:id:happy_teeth_ago:20180628003710p:plain

エラー処理について

do ~ catch文
基本形
do {
     try  エラーが予想される処理(throwキーワードが指定された処理を呼び出す場合)
    
 
    }catch{
     エラーが 発生したときの処理(普通print(error)を書きます。
}

ただ、CoreDataの中に、バイナリで持つのはおすすめしません。 画像データは大きいので、DBが遅くなります。 String型で参照を持つほうがいいです。 そのあたりは、また記載していきます。