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

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

新規登録して質問してみよう
ただいま回答率
85.48%
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

解決済

3回答

593閲覧

tableView チェックマークについて

退会済みユーザー

退会済みユーザー

総合スコア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グッド

0クリップ

投稿2017/10/01 02:50

編集2017/10/04 08:18
import UIKit class ViewController: UIViewController, UITableViewDelegate,UITableViewDataSource { @IBOutlet weak var mytableView: UITableView! var kei = [String]()//["cell 追加 ボタン"] override func viewDidLoad() { super.viewDidLoad() mytableView.delegate = self mytableView.dataSource = self // trueで複数選択、falseで単一選択 } @IBAction func addbtr(_ sender: Any) { let alert = UIAlertController(title: "タイトル", message: "メッセージ", preferredStyle: .alert) // OKボタンの設定 let okAction = UIAlertAction(title: "OK", style: .default, handler: { (action:UIAlertAction!) -> Void in // OKを押した時入力されていたテキストを表示 if let textFields = alert.textFields { // アラートに含まれるすべてのテキストフィールドを調べる for textField in textFields { self.kei.append(textField.text!) //insertは上に追加されappendは下に追加される self.kei.append("cell 追加 ボタン") } self.mytableView.reloadData() } }) alert.addAction(okAction) // キャンセルボタンの設定 let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) alert.addAction(cancelAction) // テキストフィールドを追加 alert.addTextField(configurationHandler: {(textField: UITextField!) -> Void in textField.placeholder = "テキスト" }) alert.view.setNeedsLayout() // シミュレータの種類によっては、これがないと警告が発生 // アラートを画面に表示 self.present(alert, animated: true, completion: nil) } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return kei.count } func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? { switch indexPath.row { // 選択不可にしたい場合は"nil"を返す case 1: return indexPath; // 選択可にしたい場合は"indexPath"を返す default: return nil; } } func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { if kei[indexPath.row] != "cell 追加 ボタン" { return nil } return indexPath } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) //追加した内容に対して cell.textLabel?.text = kei[indexPath.row] cell.textLabel?.textColor = UIColor.red cell.backgroundColor = UIColor.black if kei[indexPath.row] != "cell 追加 ボタン" { cell.textLabel?.textColor = UIColor.black cell.backgroundColor = UIColor.yellow } if indexPath.row == 0 { cell.textLabel?.textColor = UIColor.black cell.backgroundColor = UIColor.white } return cell } /*if kei.count > (indexPath.row + 1)使うには func tableView(_ tableView: UITableView, didSelectRowAtIndexPath: IndexPath){ を func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) -> IndexPath? {*/ func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) -> IndexPath? { let cell = tableView.cellForRow(at: indexPath) if cell?.textLabel?.text != "cell 追加 ボタン" { cell?.accessoryType = cell?.accessoryType == .checkmark ? .none : .checkmark tableView.deselectRow(at: indexPath, animated: true) return nil }else { let alert = UIAlertController(title: "タイトル", message: "メッセージ", preferredStyle: .alert) // OKボタンの設定 let okAction = UIAlertAction(title: "OK", style: .default, handler: { (action:UIAlertAction!) -> Void in // OKを押した時入力されていたテキストを表示 if let textFields = alert.textFields { // アラートに含まれるすべてのテキストフィールドを調べる for textField in textFields { self.kei.insert(textField.text!, at: indexPath.row)//indexPath.rowで1,2,3,4のような順になる //self.kei.insert(textField.text!, at:self.kei.count - 1) } self.mytableView.reloadData() } }) alert.addAction(okAction) // キャンセルボタンの設定 let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) alert.addAction(cancelAction) // テキストフィールドを追加 alert.addTextField(configurationHandler: {(textField: UITextField!) -> Void in textField.placeholder = "テキスト" }) alert.view.setNeedsLayout() // シミュレータの種類によっては、これがないと警告が発生 // アラートを画面に表示 self.present(alert, animated: true, completion: nil) return indexPath } } //cellの削除について func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { self.kei.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .fade) } } func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? { let delete = UITableViewRowAction(style: .normal, title: "削除") {ation, index in self.kei.remove(at: (indexPath.row)) tableView.deleteRows(at: [indexPath], with: .fade) } delete.backgroundColor = .red let edit = UITableViewRowAction(style: .normal, title: "編集") { action, index in let alert = UIAlertController(title: "タイトル", message: "メッセージ", preferredStyle: .alert) // OKボタンの設定 let okAction = UIAlertAction(title: "OK", style: .default, handler: { (action:UIAlertAction!) -> Void in // OKを押した時入力されていたテキストを表示 if let textFields = alert.textFields { // アラートに含まれるすべてのテキストフィールドを調べる for textField in textFields { self.kei[indexPath.row] = textField.text! //self.kei.append(textField.text!) } self.mytableView.reloadData() } }) alert.addAction(okAction) // キャンセルボタンの設定 let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) alert.addAction(cancelAction) // テキストフィールドを追加 alert.addTextField(configurationHandler: {(textField: UITextField!) -> Void in textField.placeholder = "テキスト" }) alert.view.setNeedsLayout() // シミュレータの種類によっては、これがないと警告が発生 // アラートを画面に表示 self.present(alert, animated: true, completion: nil) print("edit") } edit.backgroundColor = .orange return [delete,edit] } // trueを返すことでCellのアクションを許可しています func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { if kei.count > (indexPath.row + 1) { return true }else{ return false } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }

やりたい事
[cell 追加 ボタン]とtitleのcell以外のcellをタップした時にチェックマークをつけたり、消したりできるようにしたいです

今出来ているところ
一応cellを追加する時にチェックマークが勝手につくように出来ました

困っているところ
cellが追加された時にはまだチェックマークがついてない状態にしたいです。
それとつけることは出来たのですがタップした時にチェックマークを消せない状態にいます。
elseで消す処理は書いているのですが反応してくれません。
それで下記のようにしてみればと考えたのですがcell追加時には確かにcellが追加されなくはなったのですがそしたら今度はcellにチェックマークがつかなくなりました

func didSelectRowAtIndexPathでこのようなコードを追加したところ[cell 追加 ボタン]だけcellが追加出来るようになりました

let cell = tableView.cellForRow(at: indexPath) if cell!.accessoryType == .checkmark{ cell!.accessoryType = .none }else{ cell!.accessoryType = .checkmark }

追記
イメージ説明

@IBAction func addbtr(_ sender: Any) {    self.kei.append(textField.text!) self.kei.append("cell 追加 ボタン")

試したこと

if cell?.textLabel?.text != "cell 追加 ボタン" && cell.textLabel?.text != "textField.text!" {

@IBAction func addbtr
のなかのself.kei.append(textField.text!) をcell.textLabel?.text != "title"に当てはめればおそらく私のやりたい事が出来ると思うんですけどtextField.text!の場合""に入れても"cell 追加 ボタン"のようにチェックがつかないようにならないです。

func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) -> IndexPath? { let cell = tableView.cellForRow(at: indexPath) if indexPath.row == 0 { return nil } if cell?.textLabel?.text != "cell 追加 ボタン"{ cell?.accessoryType = cell?.accessoryType == .checkmark ? .none : .checkmark tableView.deselectRow(at: indexPath, animated: true) return nil

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

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

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

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

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

guest

回答3

0

#1 チェックマークのON/OFF状態を保存する変数を用意する

例えばchecked[Bool]など。テキストを保存しているkey[]と同様のものです。

#2 セルにチェックマークを付ける/消す

tableView(_:cellForRowAt:)の中に書きます。checked[]を見てON/OFFします。

#3 チェックマークのON/OFF切り替え

tableView(_:didSelectRowAt:)の中ではON/OFFを切り替え(checked[]の書き換え)処理を書きます。checked[]を書き換えただけではセルの表示が変わりませんので、UITableViewのreloadRows(at:with:)などを使ってセルを更新します。

投稿2017/10/02 01:26

fuzzball

総合スコア16731

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

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

0

はじめまして。

UITableViewDelegateを定義して、didSelectRowAt を実装し、タップされたときに
該当のcellにチェックをつけるとよいとおもいます。

cellForRowAt では、 .none を設定しておき、タップしたときにチェックを付ける形です。

import UIKit class ViewController: UIViewController , UITableViewDataSource, UITableViewDelegate{ ~ 略 ~ // Cell が選択された場合 func tableView(_ table: UITableView,didSelectRowAt indexPath: IndexPath) { let cell = tableView.cellForRow(at:indexPath) // チェックマークを付ける cell?.accessoryType = .checkmark }

ご参考までに。

投稿2017/10/01 03:57

KOBAYASHI.Jun

総合スコア250

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

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

fuzzball

2017/10/02 07:13

>>cellForRowAt では、 .none を設定しておき それだと、テーブルをスクロールしたときなど、セルが再生成されたときにチェックマークが消えてしまいます。
KOBAYASHI.Jun

2017/10/02 07:37

なるほど、それでは対象の値をディクショナリに保存しておいてはいかがでしょうか? 変数を用意 var dicChk = [Int: Bool]() didSelectRowAt で let cell = tableView.cellForRow(at:indexPath) if dicChk[indexPath] == false{ cell?.accessoryType = .checkmark dicChk[indexPath.row] = true }else{ cell?.accessoryType = .none dicChk[indexPath.row] = false } cellForRowAt では、 dicChk[indexPath.row].isEmpty であれば .none 値が定義されていればその値にしたがって.none / .checkmark を 設定すればよいとおもいます。
guest

0

ベストアンサー

コードが全て載っていないと思うので想像ですが、以前の続きだとすると、
「cell 追加 ボタン」だけ反応するようにコードを書いていたと思うので、
willSelectRowAt での判定は行わず、 didSelectRowAt で判定を行うようにしてあげれば反応するようになります。

Swift

1 if kei[indexPath.row] == "cell 追加" { 2 return indexPath 3 }

例えば、「cell 追加 ボタン」以外は accessoryType を変更して処理を返すようにすれば、他の処理は変更しないで実現できます。

Swift

1 if cell?.textLabel?.text != "cell 追加 ボタン" { 2 cell?.accessoryType = cell?.accessoryType == .checkmark ? .none : .checkmark 3 tableView.deselectRow(at: indexPath, animated: true) 4 return 5 }

と書きましたが、 @fuzzball さんの指摘の通り、スクロール可能になるくらいデータを追加し、スクロールするとチェックマークがスクロールする度に付いたり消えたりします。なので、 @fuzzball さんの回答の通り、チェックマークを管理するデータ保存領域が必要になります。

もし、セルのタイトルとチェック状態を別々で管理するのが不自然だと感じたら、データ構造を追加する頃合いだと思います。 チェック可能な TableView を書いてみましたので参考にしてみてください。

titleの部分にチェックつけないようにしたい

画面キャプチャのように文字通り「title」のセルにはチェックをつけたくないだけでしたら、以下のように条件を論理積で繋げれば、どちらの条件も満たさないセルのみにチェックをつけることが可能になります。

Swift

1 if cell?.textLabel?.text != "cell 追加 ボタン" && cell.textLabel?.text != "title" {

データ構造を採用するなら、プロパティに completable を追加して制御するのが自然かなと思います。
Add completable

以下の条件文で判定されるのは、「cell 追加 ボタン」「textField.text!」と言う文字列そのものと同じではないとなります。" で括ると Swift では String となり、その中に変数を書いても展開されません。

Swift

1 if cell?.textLabel?.text != "cell 追加 ボタン" && cell.textLabel?.text != "textField.text!" {

入力したテキストと比較したいなら、データを格納している kei と比較することになるのですが、追記された説明から kei を対象にしたい訳ではないと読み取れます。下記のようにした場合は、セルに表示されている文字列= kei に格納されている文字列となる訳なので何もチェックできないでしょう。

Swift

1 if cell?.textLabel?.text != "cell 追加 ボタン" && cell.textLabel?.text != kei[indexPath.row] {

なので、遡って、チェック可能なデータなのかプロパティを追加する必要があります。

投稿2017/10/02 02:16

編集2017/10/04 05:27
ykws

総合スコア1236

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

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

退会済みユーザー

退会済みユーザー

2017/10/02 07:01

willSelectRowAtの部分を消してコードを変更したら出来ました。 それとなんですがtitleの部分にチェックつけないようにしたいのですが、そのために if cell?.textLabel?.text != "cell 追加 ボタン" { の部分を if cell?.textLabel?.text != "textField.text!" { としようとしたのですがtextFieldの場合だとエラーが出て"cell 追加 ボタン"のように出来ないのですがこの場合どうしたらいいのでしょうか? いろんな方法試して見たのですがどうしても出来ませんでした。 一応if indexPath.row == 0 {  このようにすると一番最初のtitleだけチェックがつかなくなったのですがそれ以外のtitleはどうすればいいかわからない状態でいます。
fuzzball

2017/10/02 07:12

@ykwsさん 現在画面に表示されているセルに対して直接チェックマークをつけると、テーブルをスクロールした場合など、セルが再生成されたときにおかしくなると思います。
ykws

2017/10/03 06:11

@haruka-t さん、回答を編集しました。参考にしてみてください。 @fuzzball さん、指摘ありがとうございます。その通りですね
退会済みユーザー

退会済みユーザー

2017/10/03 14:36

画像内のtitleは例としてあげたもので本当は[+]ボタンのテキストアラートで入力したものなのでself.kei.append(textField.text!)の部分を関連づけさせないといけないのですがそのやり方が分からないです。 それで一応if cell?.textLabel?.text != "cell 追加 ボタン"を参考にif cell?.textLabel?.text != "textField.text!"にして見たのですがtextField.text!だと"cell 追加 ボタン"を真似ても関連させることが出来ませんでした。それでなんですがtextField.text!場合だとどのようにすればいいのか教えて頂けないのでしょうか?
ykws

2017/10/03 15:12

データ構造を採用した場合の変更について追記しました。 ただ、スクリーンショットのようなデータ構造が想像できないです。 テキストアラートで入力したもの以外のセルはどうやって追加され、どこで管理されているのでしょうか? チェックをつけたいセルとつけたくないセルがあることはわかりましたが、それの区別をどうやってつけるのかがわからないです。プログラミングの話ではなく、日本語の話です。
退会済みユーザー

退会済みユーザー

2017/10/04 02:24

質問に説明を追加しました。うまく説明出来なくお手数おかけしてすいません。それと質問に追加した説明を簡単に説明すると+ボタンで追加2つのセルにはチェックがつかずcell 追加 ボタン で追加したcellだけをチェックつけたり外せたりを出来るようになりたいです
ykws

2017/10/04 05:33

回答に追記しました。説明を追加してもらいましたが、まだどのようなデータ構造を想定しているのかがわからないです。単純に一つの文字列の配列だけでは限界があるように思い、回答には構造体を利用したプロパティの導入を記載しています。
退会済みユーザー

退会済みユーザー

2017/10/04 08:31

if indexPath.row == 0 このようにすると最初の+ボタンで追加したcellだけはチェック出来ないようにしたのですが、やはりそれ以降に+ボタンで追加するcellはタップするとチェックがついちゃいました。 なので@ykwsさんに教えて頂いた構造体を使った方法が最善の方法だと思うのですが構造体に関しては今の私の知識ではちょっと理解できないです。 それとビルドして試して気づいたのですが+ボタンでcellを追加するとチェックマークがずれていくのですがこれって後に永続保存させる時にcore data かuser defalutsを使っても改善しない問題でしょうか?
ykws

2017/10/04 08:58

indexPath.row == 0 は一番上のセルであると言う条件なので当然そうなります。 チェックマークがずれる点は @fuzzball さんの指摘の通りなので、構造体が難しい場合は、そちらの回答にあるように表示用とは別にチェック用のデータ領域を用意する必要があります。 本件において永続化は特に関係ないですが、表示用とチェック用のデータ領域をそれぞれ用意するのであれば、結果的に改善されるとは思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問