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

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

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

TableView(UITableView)とは、リスト形式で表示するコントロールで、ほとんどのアプリに使用されています。画面を「行」に分けて管理し、一般的には各行をタップした際に詳細画面に移動します。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

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

Swift

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

Q&A

解決済

1回答

967閲覧

Swiftで画面遷移した後のテーブルビューから文字列を選択し、元の画面で表示したい。

退会済みユーザー

退会済みユーザー

総合スコア0

TableView

TableView(UITableView)とは、リスト形式で表示するコントロールで、ほとんどのアプリに使用されています。画面を「行」に分けて管理し、一般的には各行をタップした際に詳細画面に移動します。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

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

Swift

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

0グッド

1クリップ

投稿2020/05/02 18:19

前提・実現したいこと

swiftで設定画面を作っております。
そこで、画面遷移し、移動先のテーブルビューから1項目を選択し、元の画面に戻ってきて、選択した文字を元の画面に表示したいと考えています。

テーブルビューを表示することまではできましたが、値を受け取し、前の画面に戻って表示することができずに困っております。

該当のソースコード

swift

1// ViewController 2import UIKit 3 4class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 5 let array = ["Next"] 6 7 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 8 return 1 9 } 10 11 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 12 let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 13 cell.textLabel?.text = String(array[indexPath.row]) 14 return cell 15 } 16 17 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 18 performSegue(withIdentifier: "toNext", sender: nil) 19 } 20 21 22 override func viewDidLoad() { 23 super.viewDidLoad() 24 25 } 26 27 28} 29

swift

1//nextViewController 2 3import UIKit 4 5class nextViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 6let array = ["A","B","C","D"] 7 8 9func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 10 return 4} 11 12func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 13 let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 14 cell.textLabel?.text = String(array[indexPath.row]) 15 return cell 16 } 17 18 19 20 21override func viewDidLoad() { 22 super.viewDidLoad() 23 24} 25 26 27 28} 29 30

イメージ説明

イメージ説明
イメージ説明

試したこと

popViewControllerを使い戻ること自体はできたのですが、値を渡すことがわかりませんでした。

どうかお力をお貸しいただければ、幸いでございます。

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

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

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

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

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

guest

回答1

0

ベストアンサー

遷移先から「戻る」のがどのタイミングなのかご質問だけでは不明ですが、navigationControllerを使っていらっしゃるので「Back」ボタンを押したタイミングで戻る、と仮定しました。

やり方は色々あるかと思いますが、

1. 遷移先ではnavigationControllerdelegateを使って、画面遷移を監視。元の画面に戻る時に遷移元のプロパティ(変数)をセット
2. 遷移元では、プロパティオブザーバを使って値が書き換わった段階で必要な処理を実行

になるのかな、という感じがします。

遷移先で文字を選択し「Back」で戻ると、元の配列に選択した文字が追加され表示されます。
また、選択した文字はprint()を使ってデバッグウインドウに表示しています。

あとは、必要に応じてお好みの処理にしていただければとおもます。

追加や気づいた点はMARK: 変更と、追加する処理はMARK: 追加とコメントしてあります。
特に深い説明はしていませんが、もし分からなければコメントください。

掲載の都合上一つのファイルで実行していますが、もちろんクラス別に分けても構いません。

swift

1import UIKit 2 3class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 4 // MARK: 追加 5 // 再表示(reloadData())を実行するため、storyBoard から引っ張っておく 6 @IBOutlet weak var tableView: UITableView! 7 8 // MARK: 変更 9 // 後から書き換えるため変数を var で宣言 10 // プロパティオブザーバを追加し、値が変更された時点で tableView を再読み込みする 11 var array = ["Next"] { 12 didSet { 13 // 値が書きかわったら table を再描画 14 tableView.reloadData() 15 } 16 } 17 // MARK: 追加 18 // 戻ってきた時に nextViewController で選ばれた文字を入れておく変数 19 var selectedString: String? { 20 didSet { 21 // 値が書き換わったら 22 // 値は nil 以外になるはずだが、念のため 23 if let selected = selectedString { 24 // ここではコンソールに値を表示しているだけだが、必要に応じて別の処理を行う 25 print("selectedString: (selected)") 26 } 27 } 28 } 29 30 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 31 // MARK: 変更 32 // いらぬトラブルを避けるためにも、配列の要素数を返した方がいい 33 //return 1 34 return array.count 35 } 36 37 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 38 let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 39 cell.textLabel?.text = String(array[indexPath.row]) 40 return cell 41 } 42 43 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 44 performSegue(withIdentifier: "toNext", sender: nil) 45 } 46 47 override func viewDidLoad() { 48 super.viewDidLoad() 49 } 50} 51 52// MARK: 変更 53// UINavigationControllerDelegate にも準拠させる 54class nextViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UINavigationControllerDelegate { 55 let array = ["A","B","C","D"] 56 // MARK: 追加 57 // 選択された行を記憶しておく変数 58 // 最初は選択されていないので、Optional型で宣言 59 var selected: Int? 60 61 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 62 // MARK: 変更 63 // いらぬトラブルを避けるためにも、配列の要素数を返した方がいい 64 //return 4 65 return array.count 66 } 67 68 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 69 let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 70 cell.textLabel?.text = String(array[indexPath.row]) 71 return cell 72 } 73 74 override func viewDidLoad() { 75 super.viewDidLoad() 76 // MARK: 変更 77 // navigationController の delegate の移譲先 78 navigationController?.delegate = self 79 } 80 81 // MARK: 追加 82 // セルが押された時の処理 83 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 84 // 押されたセルの番号(indexPath.row)を記録しておく 85 selected = indexPath.row 86 } 87 88 // MARK: 追加 89 // 戻るボタンが押された時の処理 90 // 実際には、navigationController によって画面が遷移する時に呼び出される 91 func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { 92 // 次に表示される UIViewController が viewController か否かを判別 93 if let nextVC = viewController as? ViewController { 94 // selected が nil か否かを判別 95 if let index = selected { 96 print(array[index]) 97 // viewController.selectedString に選択された文字を代入 98 nextVC.selectedString = array[index] 99 nextVC.array.append(array[index]) 100 } 101 } 102 } 103}

呼び出し側で配列を管理する例として、たとえばこのような方法もあります。

swift

1import UIKit 2 3class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 4 // MARK: 2020/05/04 追加 5 // 配列はこちらに置く 6 let detailedArray = ["A","B","C","D"] 7 8 // MARK: 2020/05/04 追加 9 // performSegue(withIdentifire:sender)が呼び出された後に呼ばれる 10 // この時点で nextViewController はインスタンス化済み 11 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 12 if let nextVC = segue.destination as? nextViewController { 13 nextVC.array = detailedArray 14 } 15 } 16 17 // 後は同じ 18} 19 20// MARK: 変更 21// UINavigationControllerDelegate にも準拠させる 22class nextViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UINavigationControllerDelegate { 23 // MARK: 2020/05/04 変更 24 // array はオプショナル型の配列として宣言しておく。 25 // 具体的な値を入れるのは、viewControllerのprepareメソッドで行っている 26 var array: [String]! 27 28 // 後は同じ 29}

segue を使って画面遷移を行なっているので、prepareメソッド内で遷移先のクラスにアクセスし、そこに値を入れています。

もちろん、これ以外にもいろいろなパターンが考えられると思いますが、ひとつの参考にしていただければと思います。

投稿2020/05/02 22:21

編集2020/05/04 09:56
TsukubaDepot

総合スコア5086

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

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

退会済みユーザー

退会済みユーザー

2020/05/04 05:51

ありがとうございます!TsukubaDepot様のご丁寧なご指南により、ほぼ希望の処理を実行することができました。戻るタイミングはボタンを押したタイミングで問題ありません。記載不足で申し訳ございませんでした。今まで全く理解していなかったと、自身の学習不足さを実感しました。また、参考までに他の方法とはどのようなものが考えられますでしょうか?
TsukubaDepot

2020/05/04 06:53

上記の処理だと、文字を選択したあとにBackを押していますが、文字を選択すると直ちに元の画面に戻るという処理もあると思います。 その場合には、tableView(_:didSelectRowAt)内部でpopViewControllerを呼ぶという方法もあるかと思います。ただ、Backボタンとセルのタップの操作をどのように使い分けるか考える必要もあると思います。
退会済みユーザー

退会済みユーザー

2020/05/04 07:30

セルを押した瞬間に戻る処理に関してはもともと実装したかったため、self.navigationController?.popViewController(animated: true) を呼び、実装しました。現在は、セルを押せば押した瞬間に値が戻り、戻るボタンを押せば何もせずに戻るようになっています。 すみませんが、もう一つ疑問が出てきまして、、、 セルを選んで戻した値を、セルの詳細に表示できるように、tableView(_:cellForRowAt)にcell.detailTextLabel?.text = selectedStringと記載し、うまくいきました。そこで初期値にもnextViewController、arrayの値を指定したいのですが、うまくいきません。 var nextView = nextViewController() var nextArray = nextView.array[2] // MARK: 追加 // 戻ってきた時に nextViewController で選ばれた文字を入れておく変数 var selectedString: String? = nextArray { didSet{ 、、、 Cannot use instance member 'nextView' within property initializer; property initializers run before 'self' is availableとエラーが表示されます。重ね重ね、申し訳ございませんが、解決策なにかご教授いただけませんでしょうか。
TsukubaDepot

2020/05/04 07:46

Cannot use instance member 'nextView' within property initializer; というエラーは、「全てのプロパティが初期化される前にあるプロパティを使うことはできない」という感じのメッセージになります。これは、クラスの初期化に関係する内容なのですが、まずはあるクラスの初期化(イニシャライザ)が呼ばれる前に、あるプロパティ(変数)に別の変数を入れることはできない、と理解してみてください。 つまり、 var nextView = nextViewController() といった感じで nextView というプロパティ(ここではインスタンス)を宣言したあと、次の行で var nextArray = nextView.array[2] といった感じでインスタンスのプロパティにアクセスしていますが、それはできない、ということです (それ以外にも問題はあるのですが、まずこの点をご理解ください)。 それを置いておいたとして、ご質問の内容がいまいちよく把握できません。Detailの部分に何か表示させたいと言うことかと思うのですが、それは初期値としては決め打ちにしたい、ということなのでしょうか。 そうであれば、nextViewController に関係なく、 var selectedString: String? = "C" { のような感じにすれば良さそうなのですが、それとはまた違いますでしょうか。
退会済みユーザー

退会済みユーザー

2020/05/04 08:47

おっしゃっていただいたように初期値を決めることが目的でした。var selectedString: String? = "C" というやり方は実行できたのですが、nextViewControllerのarrayから持ってくるやり方はできないものかと思い、ご質問させていただきました。大人しく、var selectedString: String? = "C"の方法で実施します。ご丁寧にありがとうございました。かなり助かりました!
TsukubaDepot

2020/05/04 08:58

順番の問題だと思います。 ViewControllerがインスタンス化(画面に表示)された時にはまだnextViewControllerはインスタンス化されていません。nextViewControllerがインスタンス化されるのはperformsegue()とその関連するメソッドが実行されたあとになります。つまり、それまではnextViewControllerのインスタンスにはアクセスできないわけです。 最初考えられたように、ViewControllerのプロパティにnextViewControllerのインスタンスを代入する方法だと解けたようにも見えますが、このインスタンスと、performSegueでインスタンス化されたインスタンスの実体は全く別になります。 ではどうすればいいかと言うと、一つは親となるviewControllerに全てのデータ、つまりnextViewController で使う配列も持たせて、それをnextViewControllerからアクセスする方法です。これだとインスタンス化される順番から考えても普通のやり方でアクセスできます。 とはいってもピンとは来ないかもしれませんので、ちょっと後にサンプルを書いてみますので、また後で参照してみてください。
TsukubaDepot

2020/05/04 09:57

一つの例ですが、回答の末尾に追加しました。 この後、全体としてどのようにデータを扱うか次第で細かい点は変わってくると思いますが、参考にしていただければと思います。
退会済みユーザー

退会済みユーザー

2020/05/05 14:56

参考にさせていただき、今までなんとなくでやっていた部分が解消できそうです!今後も何度も熟読し、完全に理解できるようにします。ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問