質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

3391閲覧

キャストができません UITabBarControllerからUIViewControllerへ

退会済みユーザー

退会済みユーザー

総合スコア0

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/06/23 12:35

ModalViewController内にあるchangeButton(UIButton)をタップすると
クラッシュし、コンソールに
Could not cast value of type UITabBarController to HomeViewController(UIViewController)と表示されます。

遷移は

UITabBarController ↓ FirstViewController(UITableViewController) ※UITabBarController1タブ目のビューです ↓ HomeViewController(UIViewController) ↓ ModalViewController(UIViewController)

の順です。

クラッシュの原因は
コード内でUITabBarControllerとHomeViewControllerが繋がっていない=キャストできないからと思っていますが、キャスト方法がわからない為質問します。
見て頂けないでしょうか?

よろしくお願いします。

import UIKit class CustomTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() self.navigationItem.hidesBackButton = true // 1 let firestoreController = FirestoreController() firestoreController.navigationItem.title = "タブ1" let firstNavigationController = UINavigationController(rootViewController: firestoreController) firstNavigationController.title = "" firstNavigationController.tabBarItem.image = UIImage(named: "a") viewControllers = [firstNavigationController] tabBar.isTranslucent = false } }
import UIKit class FirestoreController: UITableViewController { private var aButton: UIBarButtonItem! override func viewDidLoad() { self.navigationItem.hidesBackButton = true aButton = UIBarButtonItem(title: "ホーム", style: .plain, target: self, action: #selector(aaa)) self.navigationItem.leftBarButtonItem = aButton } @objc func aaa(_ sender: AnyObject) { let vc = HomeViewController() navigationController?.pushViewController(vc, animated: true) } }
import UIKit class HomeViewController: UIViewController { var textFromModal = "" { didSet { updatelabel(text: textFromModal) } } var textLabel = UILabel() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white set() } func set() { textLabel = UILabel(frame: CGRect(x: 0, y: 0, width: view.bounds.width - 20, height: 30)) textLabel.center = CGPoint(x: view.center.x, y: view.center.y - 50) textLabel.textAlignment = .center textLabel.text = "" view.addSubview(textLabel) // let modalButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 30)) modalButton.center = view.center modalButton.setTitle("開く", for: .normal) modalButton.setTitleColor(UIColor.blue, for: .normal) modalButton.addTarget(self, action: #selector(pushModal(sender:)), for: .touchUpInside) view.addSubview(modalButton) } @objc func pushModal(sender:UIButton) { let modal = ModalViewController(nibName: nil, bundle: nil) modal.modalTransitionStyle = .crossDissolve present(modal, animated: true, completion: nil) } func updatelabel(text: String) { textLabel.text = "a, (text)" } }
import UIKit class ModalViewController: UIViewController, UITextFieldDelegate { var changeButton = UIButton() var textField = UITextField() override func viewDidLoad() { super.viewDidLoad() // view.backgroundColor = .gray let cancelButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 30)) cancelButton.center = CGPoint(x: view.center.x - 100, y: view.center.y) cancelButton.setTitle("キャンセル", for: .normal) cancelButton.setTitleColor(UIColor.black, for: .normal) cancelButton.addTarget(self, action: #selector(pushDismiss(sender:)), for: .touchUpInside) view.addSubview(cancelButton) // changeButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 30)) changeButton.center = CGPoint(x: view.center.x + 100, y: view.center.y) changeButton.setTitle("変更", for: .normal) changeButton.setTitleColor(UIColor.black, for: .normal) changeButton.addTarget(self, action: #selector(pushChange(sender:)), for: .touchUpInside) changeButton.isEnabled = false view.addSubview(changeButton) textField = UITextField(frame: CGRect(x: 0, y: 0, width: view.bounds.width - 20, height: 30)) textField.center = CGPoint(x: view.center.x, y: view.center.y + 50) textField.delegate = self textField.text = "" textField.backgroundColor = .white view.addSubview(textField) let center = NotificationCenter.default center.addObserver(省略してます) } @objc func textFieldDidChange(notification: NSNotification) { if textField.text == "" { changeButton.isEnabled = false } else { changeButton.isEnabled = true } } func textFieldShouldReturn(_ textField: UITextField) -> Bool { self.textField.delegate = self textField.resignFirstResponder() return true } @objc func pushChange(sender:UIButton) { textField.resignFirstResponder() let originVc = presentingViewController as! HomeViewController originVc.textFromModal = textField.text! self.dismiss(animated: true, completion: nil) } @objc func pushDismiss(sender:UIButton) { self.dismiss(animated: true, completion: nil) } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

UITabBarControllerselectedViewControllerで取得できるのも、基底となっているViewControllerです。
今回の場合は、FirstViewControllerUINavigationControllerの入れ子にして、そこから、HomeViewControllerに遷移している形なので、UINavigationControllerが取得されます。
UINavigationControllerの入れ子にせず、そのままViewControllerUITabBarControllerに追加した場合は、もちろんそのViewControllerが取得できます。


間違えて新たな回答として記述してしまいましたが、

ViewControllerを取得し、これが、UINavigationControllerなので

これはUITabBarControllerのタブにセレクトするビュー(selectedViewController)は何でもUINavigationControllerになる,
という事でしょうか?

に対するコメントです。

投稿2018/06/24 16:01

編集2018/06/24 16:10
f-miyu

総合スコア1625

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/06/25 03:02

今まで私は遷移の仕組みや入れ子を全くイメージができていませんでしたが、f-miyu様のお陰で、とても理解が深まり嬉しいです。 沢山のヒントを頂きました。何度もありがとうございます!!
退会済みユーザー

退会済みユーザー

2018/07/04 04:21

f-miyu様 既に終了していますが、もし宜しければ是非教えて頂きたいです。 f-miyu様の回答にある様な遷移の仕組みは、 どちらのドキュメントを見て習得されたのでしょうか?apple公式サイトでしょうか?
f-miyu

2018/07/04 05:17

もちろんドキュメントも見ますが、ある程度仕組みがわかったら、実際にやってみて試行錯誤することが多いです。今回の場合なら、UITabBarControllerやUINavigationControllerの仕様がこうであるから、HomeViewControllerを取得するためには、こうしないといけないかもなと考えて試してみるといった感じでしょうか。あまり役に立たない回答ですみません。
退会済みユーザー

退会済みユーザー

2018/07/04 06:10

とんでもないです。 f-miyu様のおかげで今回知ったことを応用し、presentedViewControllerで値を渡したりできました。理解したことで今までとは違う見方ができるようになり、一気に楽しくなりました。 https://developer.apple.com/documentation/uikit/uitabbarcontroller?changes=_3 TabBarControllerの構造はこのドキュメントに載っていました。仰っていた通りだったので、今後もっと理解できる気がします。 きっかけを与えて頂き、ありがとうございます。
guest

0

ベストアンサー

presentingViewControllerは、一番基底となっているCustomTabBarControllerを返すので、HomeViewControllerにはキャストできません。

HomeViewControllerを取得するためには、UITabBarControllerからselectedViewControllerで現在選択されているViewControllerを取得し、これが、UINavigationControllerなので、さらにそこから、topViewControllerで最前面のViewControllerを取得することになります。

swift

1let tabVc = self.presentingViewController as! UITabBarController 2let navigationVc = tabVc.selectedViewController as! UINavigationController 3let originVc = navigationVc.topViewController as! HomeViewController 4originVc.textFromModal = textField.text!

投稿2018/06/23 15:09

f-miyu

総合スコア1625

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/06/24 15:20

f-miyu様 回答の仕組みが分かりやすくとても勉強になります。 実現したい動作を確認できました。ありがとうございます。 気になる点があります。 >>ViewControllerを取得し、これが、UINavigationControllerなので これはUITabBarControllerのタブにセレクトするビュー(selectedViewController)は何でもUINavigationControllerになる, という事でしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問