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

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

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

Xcode 7は、ソフトウェア開発のためのアップルの統合開発環境であるXcodeのバージョン。UIを作成するために用いるグラフィカルツールです。iOS9/OS X El Capitan/watchOS2に対応。Swift 2コンパイラーが搭載されています。

Swift

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

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

Q&A

解決済

1回答

3308閲覧

PageViewControllerとContenerViewを使い、スワイプ又はボタンで複数のViewControllerを遷移したいのですが、各ViewControllerの配置順が固定できません

Ando77

総合スコア13

Xcode 7

Xcode 7は、ソフトウェア開発のためのアップルの統合開発環境であるXcodeのバージョン。UIを作成するために用いるグラフィカルツールです。iOS9/OS X El Capitan/watchOS2に対応。Swift 2コンパイラーが搭載されています。

Swift

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

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

0グッド

0クリップ

投稿2016/08/31 03:41

編集2016/08/31 05:18

お世話になっております。

今回、ご質問させて頂きたい内容は、PageViewControllerとContenerViewを使い、スワイプ又はボタンで配列に格納した複数のViewController(今回は3つ)を遷移にて行き来できる、という内容を実装したいと思っております。
しかし、エラー自体は出ていないのですが、下記のような意図しない動きをしてしまい困っております。

① 立ち上げ時、配列の2番目に入っているViewControllerの画面が2つ分表示される(3ページ分しか用意していないはずが、4ページ分のスワイプができてしまう)

② 上部に配置したボタンで各ViewControllerに遷移する方法で、ページ3(サンプルでは"red")からページ1(サンプルでは"green")又は、ページ2(サンプルでは"blue")に遷移した際も、①と同じ現象が起きてします。

以上の意図しない動きが出てしまい、原因がわからず困っております。
わかりづらい表現で申し訳ありませんが、お分かりになる方がいらっしゃいましたら、原因と解決法をお教え頂きたく思います。
お手数ですが、ご回答をお願い致します。

※下記に開発コードと開発中のストーリーボード画面を記載させて頂きます。
※ストーリーボードのIDは全てswiftファイル名と同じです。
※PageViewControllerの移動法はScrollです。

イメージ説明

コード //親のコンテナビュー側のswiftファイル import UIKit struct Page_new_Settings { //UIPageViewControllerに配置するUIViewControllerクラスの名称 static let pageControllerIdentifierList : [String] = ["green","blue","red"] //UIPageViewControllerに追加するViewControllerのリストを生成する static func generateViewControllerList2() -> [UIViewController] { var viewControllers2 : [UIViewController] = [] self.pageControllerIdentifierList.forEach { viewControllerName in //ViewControllerのIdentifierからViewControllerを作る let viewController = UIStoryboard(name: "Main", bundle: nil) .instantiateViewControllerWithIdentifier("\(viewControllerName)") viewControllers2.append(viewController) } print(viewControllers2) return viewControllers2 } } class gamen3_ViewController: UIViewController, UIPageViewControllerDataSource{ // ページングして表示させる ViewControllerを保持する var pageViewController: UIPageViewController? var viewControllerIndex : Int = 0 override func viewDidLoad() { super.viewDidLoad() // ContainerView に Embed した UIPageViewController を取得する pageViewController = childViewControllers[0] as? UIPageViewController // dataSource を設定する pageViewController!.dataSource = self // 最初に表示する画面として配列の先頭の ViewController を設定する pageViewController!.setViewControllers([Page_new_Settings.generateViewControllerList2().first!], direction: .Forward, animated: false, completion: nil) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } // コンテナビュー側に配置した3つのボタンがタップされたらそれぞれのタグによってコントロラーを呼び出す @IBAction func handleButton(sender: UIButton) { switch sender.tag { case 0: let targetViewControllers : [UIViewController] = Page_new_Settings.generateViewControllerList2() pageViewController!.setViewControllers([targetViewControllers[0]], direction: .Forward, animated: false, completion: nil) if self.viewControllerIndex == 0 { return } else { self.viewControllerIndex = self.viewControllerIndex - 1 } case 1: let targetViewControllers : [UIViewController] = Page_new_Settings.generateViewControllerList2() pageViewController!.setViewControllers([targetViewControllers[1]], direction: .Forward, animated: false, completion: nil) if self.viewControllerIndex == 1 { return } else { self.viewControllerIndex = self.viewControllerIndex + 1 } case 2: let targetViewControllers : [UIViewController] = Page_new_Settings.generateViewControllerList2() pageViewController!.setViewControllers([targetViewControllers[2]], direction: .Forward, animated: false, completion: nil) if self.viewControllerIndex == 2 { return } else if(self.viewControllerIndex == 1){ self.viewControllerIndex = self.viewControllerIndex + 1 } else { self.viewControllerIndex = self.viewControllerIndex + 2 } default: break } } // 戻る方向にページ送りした時に呼ばれるメソッド func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? { let targetViewControllers : [UIViewController] = Page_new_Settings.generateViewControllerList2() if self.viewControllerIndex == 0 { return nil } else { self.viewControllerIndex = self.viewControllerIndex - 1 } return targetViewControllers[self.viewControllerIndex] } // 進む方向にページ送りした時に呼ばれるメソッド func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? { let targetViewControllers : [UIViewController] = Page_new_Settings.generateViewControllerList2() if self.viewControllerIndex == targetViewControllers.count - 1 { return nil } else { self.viewControllerIndex = self.viewControllerIndex + 1 } return targetViewControllers[self.viewControllerIndex] } }
//1ページ目 import UIKit class green: UIViewController { override func viewDidLoad() { super.viewDidLoad() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
//2ページ目 import UIKit class blue: UIViewController { override func viewDidLoad() { super.viewDidLoad() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
//3ページ目 import UIKit class red: UIViewController { override func viewDidLoad() { super.viewDidLoad() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }

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

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

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

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

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

fuzzball

2016/08/31 04:42

generateViewControllerList2()のreturnの直前に print(viewControllers2) を追加して、出力がどうなるか教えて下さい。
Ando77

2016/08/31 05:17

ご返信頂き、ありがとうございます。 ご指摘の通り、出力してみた結果が下記となります。 [<chekc.green: 0x1566d4b20>, <chekc.blue: 0x1565cf220>, <chekc.red: 0x1566d6f00>] 配列の並び自体は正しく並んでいると思いますが、なぜでしょうか? お手数ですが、引き続きご教授をお願い致します。
fuzzball

2016/08/31 05:44 編集

症状の確認ですが、①スワイプ時は、緑→青→青→赤、となるということでしょうか?②ボタン押下時は、赤画面で「緑画面」or「青画面」を押すとどうなるのでしょうか?(「①と同じ現象」の意味が分かりません)
Ando77

2016/08/31 05:57

ご返信ありがとうございます。 症状につきまして、①につきましては、ご指摘の通りの状況です。 ②につきましては、 ・赤画面で青画面を押すと、画面は青になり(右にスワイプすると落ちてしまい移動できず)、全体の位置関係は、緑←青←赤←青の順で左にスワイプしていきます。 ・赤画面で緑画面を押すと、緑←青←緑(ここに飛びます)→赤→赤、という位置関係となってしまいます。 わかりづらい表現となり申し訳ありません。 よろしくお願い致します。
fuzzball

2016/08/31 06:31

②については、ボタン押下後のスワイプによる症状ということで了解しました。(同じ現象ではないと思いますが、まぁそれは置いておいて)
fuzzball

2016/08/31 06:48

スワイプ時の「緑→青→青→赤」ですが、これは起動直後になるのではなく、ボタン押下後のスワイプで発生する症状でしょうか?
Ando77

2016/08/31 06:56

ご指摘頂きました「緑→青→青→赤」は前画面からの移動後(単なるshowによる画面遷移)すでに発生しているので、ボタン押下後ではなく、起動直後だと思われます。
fuzzball

2016/08/31 07:06

起動直後から発生していしているのであれば的外れかも知れませんが、回答を修正したので見てみて下さい。
guest

回答1

0

ベストアンサー

ボタン押下時の後半の処理、例えば「緑画面」ボタンの場合に、

swift

1if self.viewControllerIndex == 0 { 2 return 3} else { 4 self.viewControllerIndex = self.viewControllerIndex - 1 5}

という処理が書かれています。
これは「戻る方向スワイプ」の処理のコピペのようですが、ボタン押下時のコードとしては正しくありません。

ボタン押下時は、押したボタンの画面にダイレクトに遷移するのですから、「緑画面」ボタンの場合は、

swift

1self.viewControllerIndex = 0

これで良いはずです。
他のボタンについても同様に修正すればいいのですが、3つとも同じような処理なので、下記のようにsender.tagを使って簡潔に書くことができます。

swift

1@IBAction func handleButton(sender: UIButton) { 2 let targetViewControllers : [UIViewController] = Page_new_Settings.generateViewControllerList2() 3 pageViewController!.setViewControllers([targetViewControllers[sender.tag]], direction: .Forward, animated: false, completion: nil) 4 self.viewControllerIndex = sender.tag 5}

さらに修正

全体的に書き換えたので回答丸投げです。

大雑把に、

  • generateViewControllerList2()が呼ばれるたびに(緑青赤の)ViewControllerが生成されて気持ちが悪いので一度だけ生成するようにした。
  • viewControllerIndexが、実際の値と一致していないような気がしたので使うのをやめた。

修正点には「※」を付けておいたので確認して下さい。

swift

1class gamen3_ViewController: UIViewController, UIPageViewControllerDataSource { 2 3 //※最初に一度だけViewControllerのテーブルを作る 4 let targetViewControllers : [UIViewController] = Page_new_Settings.generateViewControllerList2() 5 6 // ページングして表示させる ViewControllerを保持する 7 var pageViewController: UIPageViewController? 8 //var viewControllerIndex : Int = 0 //※この変数は使わない 9 10 override func viewDidLoad() { 11 super.viewDidLoad() 12 13 // ContainerView に Embed した UIPageViewController を取得する 14 pageViewController = childViewControllers[0] as? UIPageViewController 15 16 // dataSource を設定する 17 pageViewController!.dataSource = self 18 19 // 最初に表示する画面として配列の先頭の ViewController を設定する 20 pageViewController!.setViewControllers([targetViewControllers.first!], direction: .Forward, animated: false, completion: nil) //※targetViewControllersを使うように変更 21 } 22 23 override func didReceiveMemoryWarning() { 24 super.didReceiveMemoryWarning() 25 } 26 27 // コンテナビュー側に配置した3つのボタンがタップされたらそれぞれのタグによってコントロラーを呼び出す 28 @IBAction func handleButton(sender: UIButton) { 29 //let targetViewControllers : [UIViewController] = Page_new_Settings.generateViewControllerList2() //※削除 30 pageViewController!.setViewControllers([targetViewControllers[sender.tag]], direction: .Forward, animated: false, completion: nil) 31 } 32 33 // 戻る方向にページ送りした時に呼ばれるメソッド 34 func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? { 35 36 //let targetViewControllers : [UIViewController] = Page_new_Settings.generateViewControllerList2() //※削除 37 38 if let index = targetViewControllers.indexOf(viewController) { //※インデックスを調べる 39 //print("[BEFORE] index=", index) 40 if index > 0 { 41 return targetViewControllers[index-1] //※1つ前のViewControllerを返す 42 } 43 } 44 return nil 45 } 46 47 // 進む方向にページ送りした時に呼ばれるメソッド 48 func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? { 49 50 //let targetViewControllers : [UIViewController] = Page_new_Settings.generateViewControllerList2() //※削除 51 52 if let index = targetViewControllers.indexOf(viewController) { //※インデックスを調べる 53 //print("[AFTER] index=", index) 54 if index < targetViewControllers.count-1 { 55 return targetViewControllers[index+1] //※1つ先のViewControllerを返す 56 } 57 } 58 return nil 59 } 60 61}

投稿2016/08/31 06:36

編集2016/08/31 08:23
fuzzball

総合スコア16731

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

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

Ando77

2016/08/31 07:22

ボタン押下時のコードの訂正につきまして、ご指摘ありがとうございます。 修正後、赤画面から「緑画面ボタン」で戻った際には、やはり「緑→青→青→赤」になってしまい、赤画面から「青画面ボタン」で戻った際には、落ちることは無くなりましたが、 ① 始めに緑側へスワイプした時 「緑←緑←青(ここに戻る)→赤」 ② 始めに赤側へスワイプした時 「緑←青(ここに戻る)→赤→赤」 上記の2パターンになってしまいます。 fuzzball様側では、問題なく動作しているということは、コードではなく、ストーリーボード上の制約や設定に問題があるのでしょうか? お手数をかけてしまい、大変恐れ入ります。
fuzzball

2016/08/31 07:31

「問題なく動作している」というのは私の勘違い‥というか調査不足です。その後、調べた後で回答を修正しました。もう少し調べてみます。
Ando77

2016/08/31 07:48

ご返信ありがとうございます。 私一人では、知識が少なく、とても原因がわかりそうにありませんので、 大変お手数ですが、引き続き宜しくお願い致します。
Ando77

2016/08/31 08:38

fuzzball様 ご回答の編集ありがとうございます。 ご指摘頂きました編集点は自分では気付けなかった点なので、大変参考になりました。 頂きましたコードにて動かしたところ、何の誤作動もなく動作致しました。 編集頂きました各点を一つずつ見直して、今後のために勉強させて頂きたいと思います。 わかりにくい説明を理解して頂いた上に、複数回にわたりご回答頂き、大変お世話になりました。誠にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問