イメージ画像
アプリの概要
1つの画面に別々の画像を表示させるアプリです。
右下のプラスボタンをタップすると、UIAlertControllerが表示され、アルバムの写真を表示したりカメラで撮影した写真を表示するようにっています。
表示されている画像を「tapgesturerecognizer」でタップするとモーダルで画面遷移します。
その際に、下記のエラーが表示されました。
エラー内容
デバックの内容(一部)
Could not cast value of type 'select.rightViewController' (0x100987ed0) to 'select.leftViewController' (0x100987dc8). 2020-05-16 13:04:56.387510+0900 select[2904:123395] Could not cast value of type 'select.rightViewController' (0x100987ed0) to 'select.leftViewController' (0x100987dc8). (lldb)
試したこと
「rightViewController」から先に作り始めたのですが、その際の画面遷移ではエラーはなく値を渡して遷移することができました。
「leftViewController」を作成して、「override func prepare(for segue: UIStoryboardSegue, sender: Any?) {}」に下記のコードを入力したところ現在のエラーに至っています。
let leftVC = segue.destination as! leftViewController leftVC.leftView = leftImageView.image! leftVC.leftText = leftTextField.text! }
実現したいこと
- 画像が表示されていない時はタップジェスチャーを無効にして画面遷移しないようにしたい。
- 値を渡して画面遷移をしたい。
Viewcontroller.swift
import UIKit import Photos class ViewController: UIViewController,UIImagePickerControllerDelegate, UINavigationControllerDelegate,UITextFieldDelegate { @IBOutlet weak var tapButton: UIButton! @IBOutlet weak var rightImageView: UIImageView! @IBOutlet weak var leftImageView: UIImageView! @IBOutlet weak var rightTextField: UITextField! @IBOutlet weak var leftTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() rightTextField.adjustsFontSizeToFitWidth = true tapButton.layer.cornerRadius = 20.0 PHPhotoLibrary.requestAuthorization { (states) in switch(states){ case .authorized: break case .denied: break case .notDetermined: break case .restricted: break } } } //アラートが画面を表示する @IBAction func menuTapped(_ sender: Any) { // styleをActionSheetに設定 let alertSheet = UIAlertController(title: "選択画面", message: "選んでください", preferredStyle: UIAlertController.Style.actionSheet) // 自分の選択肢を生成 let action1 = UIAlertAction(title: "右:アルバムで選択して表示する", style: UIAlertAction.Style.default, handler: { (action: UIAlertAction!) in let sourceType:UIImagePickerController.SourceType = UIImagePickerController.SourceType.photoLibrary if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary){ // すでに宣言したプロパティを使用 self.firstPicker.sourceType = sourceType self.firstPicker.delegate = self self.present(self.firstPicker, animated: true, completion: nil) } } ) let action2 = UIAlertAction(title: "右:カメラで撮影して表示する", style: UIAlertAction.Style.default, handler: { (action: UIAlertAction!) in let sourceType:UIImagePickerController.SourceType = UIImagePickerController.SourceType.camera if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera){ // すでに宣言したプロパティを使用 self.firstPicker.sourceType = sourceType self.firstPicker.delegate = self self.present(self.firstPicker, animated: true, completion: nil) } } ) let action3 = UIAlertAction(title: "左:アルバムで選択して表示する", style: UIAlertAction.Style.destructive, handler: { (action: UIAlertAction!) in let sourceType:UIImagePickerController.SourceType = UIImagePickerController.SourceType.photoLibrary if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary){ // すでに宣言したプロパティを使用 self.secondPicker.sourceType = sourceType self.secondPicker.delegate = self self.present(self.secondPicker, animated: true, completion: nil) } } ) let action4 = UIAlertAction(title: "左:カメラで撮影して表示する", style: UIAlertAction.Style.destructive, handler: { (action: UIAlertAction!) in let sourceType:UIImagePickerController.SourceType = UIImagePickerController.SourceType.camera if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera){ // すでに宣言したプロパティを使用 self.secondPicker.sourceType = sourceType self.secondPicker.delegate = self self.present(self.secondPicker, animated: true, completion: nil) } }) let action5 = UIAlertAction(title: "cancel", style: UIAlertAction.Style.cancel, handler: { (action: UIAlertAction!) in }) // アクションを追加. alertSheet.addAction(action1) alertSheet.addAction(action2) alertSheet.addAction(action3) alertSheet.addAction(action4) alertSheet.addAction(action5) self.present(alertSheet, animated: true, completion: nil) } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { picker.dismiss(animated: true, completion: nil) } let firstPicker = UIImagePickerController() let secondPicker = UIImagePickerController() func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { if let pickedImage = info[.originalImage] as? UIImage { // ピッカーの種類がどちらかを判定する if(picker == self.firstPicker) { rightImageView.image = pickedImage } else if(picker == self.secondPicker) { leftImageView.image = pickedImage } else { // 何か処理があれば記載 } picker.dismiss(animated: true, completion: nil) } } @IBAction func rightTappedGesture(_ sender: Any) { performSegue(withIdentifier: "right", sender: nil) } @IBAction func leftTappedGesture(_ sender: Any) { performSegue(withIdentifier: "left", sender: nil) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { let rightVC = segue.destination as! rightViewController rightVC.rightView = rightImageView.image! rightVC.rightText = rightTextField.text! let leftVC = segue.destination as! leftViewController leftVC.leftView = leftImageView.image! leftVC.leftText = leftTextField.text! } func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { view.endEditing(true) } }
rightViewController.swift
import UIKit class rightViewController: UIViewController { @IBOutlet weak var backButton: UIButton! @IBOutlet weak var rightLabel: UILabel! var rightView = UIImage() var rightText = String() @IBOutlet weak var rightImage: UIImageView! override func viewDidLoad() { super.viewDidLoad() rightLabel.text = rightText rightLabel.adjustsFontSizeToFitWidth = true rightImage.image = rightView backButton.layer.cornerRadius = 20.0 } @IBAction func back(_ sender: Any) { dismiss(animated: true, completion: nil) } }
文字数制限のため「leftViewController」省略
prepare(for segue:) は遷移先に応じて場合分けが必要です。
hoshi-takanoriさんがおっしゃっている通りなのですが、少し補足すると segue.identifire の内容に応じて場合分けが必要です。
https://i-app-tec.com/ios/tap_gesture.html
上記URLの「新しい ViewControllerクラス を作成」辺りからが参考になるかと思います。
hoshi-takanori様
TsukubaDepot様
アドバイスいただきありがとうございます。URL感謝します。
if文で分けてみたら、右側の画面は値を渡して遷移することができました。
ただ、左側の画面を押した時に、「Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value」が出るようになりました。
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "right") {
let rightVC = segue.destination as! rightViewController
rightVC.rightView = rightImageView.image!
rightVC.rightText = rightTextField.text!
}else if (segue.identifier == "left") {
let leftVC = segue.destination as! leftViewController
leftVC.leftView = leftImageView.image!
leftVC.leftText = leftTextField.text!
}
}
IBOuletで不備がないか調べてみます。
UILabelのアウトレット接続が外れていました。
回答1件
あなたの回答
tips
プレビュー