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 ) } }