まず最初にプロパティ名は小文字で開始して下さい。この回答ではそのつもりで記載します。
Quiz2Cell
クラスにはおそらく、
swift
1class Quiz2Cell: UITableViewCell {
2 @IBOutlet weak var quizLabel: UILabel!
3 @IBOutlet var quizButton0: UIButton!
4 @IBOutlet var quizButton1: UIButton!
5 ...
のようにボタン 5 個分のアウトレット接続があるのだと思いますが、まずこれをやめましょう。
次のように配列に 5 個のボタンをまとめておく アウトレットコレクション を使ってください。
swift
1class Quiz2Cell: UITableViewCell {
2 @IBOutlet weak var quizLabel: UILabel!
3 @IBOutlet var quizButtons: [UIButton]!
ストーリーボードで左側のボタンから順番にこのプロパティへアウトレット接続すればその順番のまま格納されます。
また、どのボタンが選択状態にあるのかを Quiz2Cell
自身も Int
型のプロパティで持ちましょう。
swift
1var currentQuizButtonIndex: Int = 0
次に、ボタンアクションを作ります。ひとつのアクションには複数のボタンを紐付けられます。 アウトレット接続と同じ要領です。5 個のボタン全てをこのアクションに紐づけて下さい。どのボタンを押しても押されたボタンが sender
に渡されつつこのアクションが実行されます。
ここで、アウトレットコレクションにしたボタンの配列から押したボタンを検索すれば、そのインデックス=ボタンの位置になります。currentQuizButtonIndex
にセットしましょう。
swift
1class Quiz2Cell: UITableViewCell {
2 ...
3
4 @IBAction func didTapQuizButton(_ sender: UIButton) {
5 if let index = self.quizButtons.firstIndex(of: sender) {
6 self.currentQuizButtonIndex = index
7 }
8 }
currentQuizButtonIndex
の更新タイミングに合わせて、選択したボタンを黒丸へ、それ以外を白丸に戻す処理が必要です。
インデックスを渡したら、ボタンの配列の列挙を行い該当するボタンだけ黒丸になるよう関数を用意します。以下の関数はボタンタイトルで黒丸、白丸を表現していると仮定しています。
swift
1private func updateCurrentQuizButton(_ currentIndex: Int) {
2 for (index, quizButton) in self.quizButtons.enumerated() {
3 if index == currentIndex {
4 quizButton.setTitle("●", for: .normal)
5 } else {
6 quizButton.setTitle("○", for: .normal)
7 }
8 }
9}
プロパティには値のセット前後に処理を行わせる プロパティオブサーバ を記述できます。値をセットしたら処理を実行するよう didSet
ブロックを currentQuizButtonIndex
に追記し、上記の関数を実行させましょう。
swift
1var currentQuizButtonIndex: Int = 0 {
2 didSet {
3 let value = self.currentQuizButtonIndex
4 self.updateCurrentQuizButton(value)
5 }
6}
これで、ボタンを押したら、その位置をプロパティにセットし、そのセット後にボタンのタイトルを更新する処理の流れが組めました。
次は TableViewController が値の変更を知ることができるようにします。それには プロトコル と デリゲート が適しています。
Quiz2Cell
のファイルに次のようなプロトコルを追記します。そしてそのプロトコル型のプロパティ delegate
を追加します。
swift
1protocol Quiz2CellDelegate {
2 func quiz2CellDidChangeCurrentQuizButtonIndex(_ cell: Quiz2Cell, index: Int)
3}
4
5class Quiz2Cell: UITableViewCell {
6 @IBOutlet weak var quizLabel: UILabel!
7 @IBOutlet var quizButtons: [UIButton]!
8 var delegate: Quiz2CellDelegate?
9 ...
10}
このプロトコルに定義した関数は名前の通り、選択されたクイズボタンのインデックスが変更されたという通知です。インデックスの変更時、このメソッドを delegate
にセットされたものが実行するよう、currentQuizButtonIndex
の didSet
ブロックに追記しましょう。
swift
1var currentQuizButtonIndex: Int = 0 {
2 didSet {
3 let value = self.currentQuizButtonIndex
4 self.updateCurrentQuizButton(value)
5 if let delegate = self.delegate {
6 delegate.quiz2CellDidChangeCurrentQuizButtonIndex(self, index: value)
7 }
8 }
9}
これで、インデックスをセットしたタイミングで delegate
にセル自身とボタンの位置を示すインデックスが渡るようになりました。
TableViewController
でこのプロトコルを採用し、通知を受け取るメソッドを実装します。
swift
1class TableViewController: UITableViewController, Quiz2CellDelegate {
2 ...
3
4 func quiz2CellDidChangeCurrentQuizButtonIndex(_ cell: Quiz2Cell, index: Int) {
5 }
6}
セルの生成時に delegate
へ TableViewController
自身を入れましょう。これまでの変更に沿い、セルの生成内容は次のようになります。
swift
1override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
2 guard let cell = tableView.dequeueReusableCell(withIdentifier: "QuizCellIdentifier") as? Quiz2Cell else {
3 fatalError("Could not dequeue a cell")
4 }
5
6 let series1 = series_questions[indexPath.row]
7 cell.quizLabel.text = series1.text
8 cell.currentQuizButtonIndex = series1.number // 選択番号をセットするだけ
9 cell.delegate = self // デリゲートを設定
10
11 return cell
12}
最後です。実装したデリゲートメソッドではセルが渡されているので、テーブルビューにセルを渡すだけでセルのインデックスパスが取得できます。これは series_questions
と対応しているわけだから、次のように対応する Question
オブジェクトを取得して、number
プロパティに渡された index
をセットすれば series_questions
に現在の選択状態が反映されることになります。
swift
1// varで宣言していないとその要素のプロパティも変更できないので注意
2var series_questions: [Question] = [
3 Question(text: "質問 1"),
4 Question(text: "質問 2"),
5 ...
6]
7
8...
9
10func quiz2CellDidChangeCurrentQuizButtonIndex(_ cell: Quiz2Cell, index: Int) {
11 if let indexPath = self.tableView.indexPath(for: cell) {
12 self.series_questions[indexPath.row].number = index
13 }
14}
これで、回答完了ボタンの処理でも series_questions
を参照するだけでそれぞれのアンケートのボタン位置が調べられます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/10/16 20:57