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

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

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

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

Q&A

解決済

2回答

3786閲覧

segmented controlで画面遷移をしたい

sam3457

総合スコア52

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

0グッド

1クリップ

投稿2018/03/06 05:13

編集2018/03/06 12:05

以下の様にstoryboardで作ったpageviewcontollerをsegmentedcontrolでも遷移する様にしたいです。
イメージ説明

以下がsegmentedcontrolがある画面のクラス

swift

1import UIKit 2 3class SegViewController: UIViewController { 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 8 // Do any additional setup after loading the view. 9 } 10 11 @IBAction func changePage(_ sender: UISegmentedControl) { 12 13 let vc = ViewController() 14 15 switch sender.selectedSegmentIndex { 16 case 0: 17 vc.getFlow() 18 case 1: 19 vc.getChat() 20 default: 21 vc.getFlow() 22 } 23 24 } 25 26 override func didReceiveMemoryWarning() { 27 super.didReceiveMemoryWarning() 28 // Dispose of any resources that can be recreated. 29 } 30 31 32 33 34}

以下がpageviewcontrollerのクラスです。

swift

1import UIKit 2 3class ViewController: UIPageViewController { 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 self.setViewControllers([getFlow()], direction: .forward, animated: true, completion: nil) 8 self.dataSource = self as UIPageViewControllerDataSource 9 } 10 11 func getFlow() -> FlowViewController { 12 return storyboard!.instantiateViewController(withIdentifier: "flow") as! FlowViewController 13 } 14 15 func getChat() -> ChatViewController { 16 return storyboard!.instantiateViewController(withIdentifier: "chat") as! ChatViewController 17 } 18 19 20 21 override func didReceiveMemoryWarning() { 22 super.didReceiveMemoryWarning() 23 } 24} 25 26extension ViewController : UIPageViewControllerDataSource { 27 28 func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { 29 if viewController.isKind(of: ChatViewController.self) { 30 // 2 -> 1 31 return getFlow() 32 } else { 33 // 1 -> end of the road 34 return nil 35 } 36 } 37 38 func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { 39 if viewController.isKind(of: FlowViewController.self) { 40 // 1 -> 2 41 return getChat() 42 } else { 43 // 3 -> end of the road 44 return nil 45 } 46 } 47} 48

こちらをビルドし、segmentedcontrolの選択を変更するとpageviewcontrollerのクラスでエラーが発生します。
イメージ説明

このエラーに従ってアンラップしても
Initializer for conditional binding must have Optional type, not 'ChatViewController'
とオプショナル型が必要だと出てきます。

また、画面遷移はここの部分で行っているのではないのでしょうか?

swift

1 func getFlow() -> FlowViewController { 2 return storyboard!.instantiateViewController(withIdentifier: "flow") as! FlowViewController 3 } 4 5 func getChat() -> ChatViewController { 6 return storyboard!.instantiateViewController(withIdentifier: "chat") as! ChatViewController 7 } 8

ご存知の方がいらっしゃいましたらよろしくお願いいたします。

追記
以下がprint(storyboard)の出力になります。
イメージ説明

以下がstoryBoardです。
イメージ説明

SegViewControllerとFlowViewController、およびChatViewControllerをセグエでつないだものです
イメージ説明

実行して、segmentedcontrolを選択すると新しい画面としてChatViewControllerが出てきてしまいます。
イメージ説明

SegViewControllerにContainerViewを乗せ、ChatVeiwControllerにSegue(embed)でつないだものです。
イメージ説明

newmtさん
setViewControllersにgetChat()を追記したところ、立ち上がる前に落ちてしまいました。
こちらがその時のデバックエリアの画面です。

'The number of view controllers provided (2) doesn't match the number required (1) for the requested transition'
'提供されたビューコントローラの数(2)が、要求された遷移のために必要な数(1)と一致しません'

とありました。

イメージ説明

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

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

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

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

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

fuzzball

2018/03/06 05:49

Storyboardの画像が小さくて確認できないのですが、ViewControllerはどうやって生成しているでしょうか?また、getChat()の中で print(storyboard) と print(type(of: storyboard!.instantiateViewController(withIdentifier: "chat")) の出力を教えて下さい。
sam3457

2018/03/06 07:50

修正依頼ありがとうございます。storyboardのViewControllerはUI部品のライブラリペインからドラックして、その後UIPageViewControllerを継承したViewControllerクラスを接続しました。print(type(of: storyboard!.instantiateViewController(withIdentifier: "chat"))を記述したのですが、エラーになってしまうのでひとまずコメントアウトしてprint(storyboard)をgetChat()の中に記述しました。こちらはビルドしてみるとnilになっていました。質問を修正しておきます。
sam3457

2018/03/06 07:51

UI部品のライブラリペインからドラックしたものはPageViewControllerです。
fuzzball

2018/03/06 07:57 編集

(deleted)
fuzzball

2018/03/06 08:01

Storyboardの画像を大きく出来ませんか?
guest

回答2

0

SegViewController内の

swift

1let vc = ViewController()

これダメなのでは?
SegmentedControllerを押すたびにViewController()を生成しています。

【追記】

Storyboardを見て、ようやくやりたいことが分かりました。

  • 現在のchangePage()の中身を破棄する。
  • SegViewControllerと、FlowViewControllerおよびChatViewControllerをセグエで繋ぐ。
  • changePage()の中で、performSegue(withIdentifier:sender:)を使ってセグエを発動させる。(押されたセグメントによってセグエを選択する)

こんな感じでいいのでは。

投稿2018/03/06 08:00

編集2018/03/06 08:30
fuzzball

総合スコア16731

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

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

sam3457

2018/03/06 09:57 編集

回答ありがとうございます。 現在のchangePage()の中身を破棄し、SegViewControllerとFlowViewController、およびChatViewControllerをセグエでつないだのですが、そうしたところFlowViewControllerとChatViewControllerがSegViewControllerの画面のサイズに修正されてしまい、かなり小さくなってしまいました。 また、実行してsegmentedControlを選択すると新しい画面としてバックボタン付きで出てしまい、その画面ではSegViewControllerに配置したsegmentedControlが消えてしまいました。 新しい画面としてではなく、segmentedControlを残したままスワイプした時と同じ様に横に遷移するようにしたいのですが、そのような動きもsegueを引いて行うのでしょうか? 質問の説明不足から、後出しになってしまい本当に申し訳ありません。
fuzzball

2018/03/06 10:12 編集

>>かなり小さくなってしまいました それは、あくまでStoryboard上での見た目のサイズなので気にしなくてかまいません。 >>segmentedControlを残したまま SegViewControllerにContainerViewを乗せればいいかも知れません。
sam3457

2018/03/06 11:39

>>SegViewControllerにContainerViewを乗せればいいかも知れません。 SegVeiwControllerにContainerViewをのせる、、StoryBoardのNavigationControllerの隣のViewControllerからSegViewControllerにContainerVeiwを伸ばしているのですが、そこからさらにChat,FlowViewControllerに伸ばすということでしょうか? 質問に試してみた画像を貼ります。 また、segmentedcontrolの選択肢をタップすると新しい画面として遷移してしまうのですが、やはりsegueで繋げないといけないのでしょうか?
sam3457

2018/03/07 03:31

申し訳ありません。ContainerViewについてもっとよく調べてみてからこの画面を作っていこうかと思います。リンクありがとうございます。
guest

0

ベストアンサー

新しくUIStoryboardインスタンスを取得しても変わらないでしょうか?

Swift

1 2// Main.storyboardを使用していることを前提にしています 3let s = UIStoryboard.init(name: "Main", bundle: nil) 4s.instantiateViewController(withIdentifier: "flow") as! FlowViewController 5

【追記】
下記のsetViewControllersにgetChat()を追記したらどうでしょうか?

~~self.setViewControllers([getFlow(), getChat()], direction: .forward, animated: true, completion: nil)
~~

【追記2】
すいません。↑は別のものと勘違いしていました。
ご質問の追記を見て色々試してみたのですが中々うまくいかず、上記とは少し違う形で一応segmentedControlを使って画面遷移する方法はあるのですが、これでやりたいことが達成されますでしょうか?
違っていたらごめんなさい。

イメージ説明

ViewController.swift

1 2import UIKit 3 4class ViewController: UIViewController { 5 6 @IBOutlet weak var segmentedControl: UISegmentedControl! 7 override func viewDidLoad() { 8 super.viewDidLoad() 9 } 10 11 override func viewDidAppear(_ animated: Bool) { 12 super.viewDidAppear(animated) 13 changeToFlowController() 14 } 15 func getFlow() -> FlowViewController { 16 17 let storyboard = UIStoryboard(name: "Main", bundle: nil) 18 return storyboard.instantiateViewController(withIdentifier: "flow") as! FlowViewController 19 } 20 21 func getChat() -> ChatViewController { 22 let storyboard = UIStoryboard(name: "Main", bundle: nil) 23 return storyboard.instantiateViewController(withIdentifier: "chat") as! ChatViewController 24 } 25 26 @IBAction func changePage(_ sender: UISegmentedControl) { 27 28 switch sender.selectedSegmentIndex { 29 case 0: 30 changeToFlowController() 31 case 1: 32 changeToChatController() 33 default: 34 changeToFlowController() 35 } 36 } 37 38 func changeToFlowController() { 39 40 let vc = getFlow() 41 removeLast() 42 add(vc) 43 44 } 45 46 func changeToChatController() { 47 let vc = getChat() 48 removeLast() 49 add(vc) 50 } 51 52 53 func add(_ childController: UIViewController) { 54 addChildViewController(childController) 55 view.addSubview(childController.view) 56 childController.didMove(toParentViewController: self) 57 view.bringSubview(toFront: segmentedControl) 58 } 59 60 func removeLast() { 61 guard let viewController = self.childViewControllers.last else { 62 return 63 } 64 viewController.view.removeFromSuperview() 65 viewController.removeFromParentViewController() 66 } 67}

投稿2018/03/06 05:56

編集2018/03/06 23:31
newmt

総合スコア1277

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

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

sam3457

2018/03/06 08:29

回答ありがとうございます。お教え頂いたコードをgetFlow()とgetChat()(idとas以降はchatViewControllerに合わせました)の中に記述したところ、依然としてsegmentedcontrolの右の選択肢であるchatの方をタップしたところで同じエラーが出てしまいました。
newmt

2018/03/06 08:58

回答を追記しました。こちらではいかがでしょうか?
sam3457

2018/03/06 11:49

ありがとうございます。 結果を質問に追記します。
newmt

2018/03/06 23:31

すいません。別のものと勘違いしていました。回答を追記しました。違っていたらごめんなさい。
sam3457

2018/03/07 04:23

お手間とらせてしまい申し訳ありません。 ありがとうございます。お教え頂いたように新しく作った結果、segmentedcontrolで遷移ができました! こちらをこれから自力で画面スワイプでもChat/FlowViewConroller間で遷移できるようにしようと思っているのですが、そのコードはChat,FlowViewControllerに書いていけば良いのでしょうか?
newmt

2018/03/07 09:48

ViewController内でUISwipeGestureRecognizerを設定し、 スワイプの動きに合わせてChat/FlowViewConrollerとsegmentedControlを変えれば実現可能です。
sam3457

2018/03/07 10:03

なるほど、、最後まで本当にありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問