Swift @escaping属性のクロージャとは

Swiftにおけるクロージャには、いくつかの属性を指定できます。

その1つに@escapingがありますが、画像データを表示する箇所で利用したので、実際のコードで説明します。

問題点 imageをバインディングしているため、nilのときにはsaveDiary が呼ばれす保存されない状態になっている

    @IBAction func doneButtonTapped(_ sender: Any) {

//ここでバインディングしているので、画像がないときはDiaryそのものが保存されない
        uploadPhoto() { imgUrl in
            if let imgUrl = imgUrl {
                self.saveDiary(photoRef: imgUrl)
            }
        }
    }

呼び出している関数

upliadPhoto からsaveDiary を呼び出している

このときに 引数に @escaping属性 のクロージャを利用

  private func uploadPhoto(callback: @escaping ((String?)->Void)) {

//imageが無いときは,callbackにnilを渡すことで、引数なしになる
//saveDiaryには引数String> のオプショナルにしているので問題ない
        guard let imgData = diaryImage.image?.jpegData(compressionQuality:0.1) else {
            callback(nil)
            return
        }
        let fileName = NSUUID().uuidString
        let storageRef = Storage.storage().reference().child("diaryImages").child(fileName)

        storageRef.putData(imgData, metadata: nil) { (metadata, error) in

            if let error = error { print(error); return }

            callback(metadata?.path)
        }

    }
//imageがなく、引数が無いことがあるので引数の型はString? にしておく
private func saveDiary(photoRef: String?) {
        guard  let title_1 = title_1.text else { return }
        guard  let title_2 = title_2.text else { return }
        guard  let title_3 = title_3.text else { return }

        let new_diary = userREF.collection(DIARY_REF).document()
        var data = [
            TITLE_1 : title_1,
            TITLE_2 : title_2,
            TITLE_3 : title_3,
        ]

//imageが無いことがあるので、インスタンスに追加するように変更する
        data[PHOTO] = photoRef
        new_diary.setData(data) { error in
            if let err = error {
                debugPrint(err)
            }else{
                let nextVC = UIStoryboard(name: "DiaryIndexController", bundle: nil).instantiateViewController(identifier: "DiaryIndexController")
                nextVC.modalPresentationStyle = .fullScreen
                self.present(nextVC, animated: true, completion: nil)

            }
        }
    }

なのでimageが無いときはnilを返すだけで良い

変更後の doneButtonTapped (tailing Closure)

    @IBAction func doneButtonTapped(_ sender: Any) {
        uploadPhoto() { imgUrl in self.saveDiary(photoRef: imgUrl ) }
        
    }