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

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

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

解決済

2回答

744閲覧

Cellのチェックマークの状態をUserDefaultsで保存したい

hik_

総合スコア42

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クリップ

投稿2018/12/15 15:43

編集2018/12/15 15:44

前提・実現したいこと

勉強の為、簡易なtodoアプリを作っていまして、その中の機能でCellにチェックマークをつけたり、外したりする機能を実装したいのですが、
画面遷移をするとCellにチェックマークをつけていても消えてしまうので、チェックマークの状態をUserDefautlsで保存したく、
変数の配列を用意して、配列の中をUserDefautlsに保存しようかと思うのですが、
文字の場合は

var yotei = [String]()

と出来ますが、チェックマークの状態はどのような型なのでしょうか?

試したこと

色々とチェックマークの場合の型を調べたり、思い当たるコードを書いてみているのですが、分からない状況です。
ご教示頂けると幸いです。

補足情報(FW/ツールのバージョンなど)

Swift4 Xcode10

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

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

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

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

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

guest

回答2

0

ベストアンサー

いろいろなやり方ができると思います。
要は2択に分けられればいい事になります。

通常はBool型もしくはInt型(0 or 1)で行うのが、
わかりやすいのではないでしょうか?

  1. Bool型の配列を作り
  2. cellForRowAtで配列を読み込み、checkmarkを表示するかを記入。
  3. didSelectRowAtで押すごとにそのindexPathを利用し、

その場所のBoolをひっくり返し、tableviewを読み込み直す

という手順になります。

他には少し強引ですが、
文字列の文字数を条件分岐にしたり、
特定の文字で条件分岐できなくもないと思います。

いかに一応サンプルコード載せておきます。

Swift

1# sampletableViewContorller.swift 2 3class InputViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 4 5 var itemArray: [String] = ["いちご", "バナナ", "リンゴ"] 6 var checkMarkArray: [Bool] = [] 7 8 @IBOutlet weak var tableView: UITableView! 9 10 override func viewDidLoad() { 11 super.viewDidLoad() 12 13 for n in 0 ... itemArray.count - 1 { 14 checkMarkArray.append(false) 15 } 16 } 17 18 19 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 20 return itemArray.count 21 } 22 23 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 24 let cell = tableView.dequeueReusableCell(withIdentifier: "sampleCell") 25 26 cell.textLabel.text = itemArray[indexPath.row] 27 if checkMarkArray[indexPath.row] == true { 28 cell.accessoryType = .checkmark 29 } 30 return cell 31 } 32 33 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 34 checkMarkArray[indexPath.row] = changeBool(value: checkMarkArray[indexPath.row]) 35 self.tableView.reloadData() 36 } 37 38 func changeBool(value: Bool) -> Bool { 39 if value == true { 40 return false 41 } else { 42 return true 43 } 44 } 45

ところどころ!が抜けているかもしれませんが、、、
これで動くはずです。

助けになれば幸いです。

追伸、肝心のuserdefaultsに保存を記載してなかったですね。
以下のように修正していただければ大丈夫だと思います。
ちなみにitemArrayはletでいいです。
checkmarkArrayはMarkとmarkが混じってて、
Xcodeに指摘されると思うので、そこも治してください。

Swift

1# sampletableViewContorller.swift 2 3 override func viewDidLoad() { 4 super.viewDidLoad() 5 6     checkmarkArray = UserDefaults.standard.array(forKey: "checkmarkarray") as! [Bool] 7 if checkmarkArray.count == 0 { 8 for n in 0 ... itemArray.count - 1 { 9 checkmarkArray.append(false) 10 } 11 UserDefaults.standard.set(checkmarkArray, forKey: "checkmarkarray") 12 } 13 14 } 15 16 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 17 checkMarkArray[indexPath.row] = changeBool(value: checkMarkArray[indexPath.row]) 18 UserDefaults.standard.set(checkmarkArray, forKey: "checkmarkarray") 19 self.tableView.reloadData() 20 } 21 22 override func viewWillAppear() { // これも忘れてました、戻る時にdataの更新が必要です。 23 self.tableView.reloadData() 24 }

投稿2018/12/15 23:46

編集2018/12/16 01:23
hameji001

総合スコア639

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

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

hik_

2018/12/17 04:18

ご回答ありがとうございます。また返信が遅れすみません。 コードまで書いていただきありがとうございます!分かりやすくて助かります。 実践してみようと思います。 ありがとうございました。
hik_

2018/12/18 04:53

コードを実行してみたところ以下の部分でエラーが起こるのですが、何が起因しているのでしょうか? ご教示頂けると幸いです。 import UIKit class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource { let itemArray: [String] = ["いちご", "バナナ", "りんご"] var checkMarkArray: [Bool] = [] @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() // エラーが起きる checkMarkArray = UserDefaults.standard.array(forKey: "checkmarkarray") as! [Bool] if checkMarkArray.count == 0 { for _ in 0 ... itemArray.count - 1 { checkMarkArray.append(false) } UserDefaults.standard.set(checkMarkArray, forKey: "checkmarkarray") } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return itemArray.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel!.text = itemArray[indexPath.row] if checkMarkArray[indexPath.row] == true { cell.accessoryType = .checkmark } return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { checkMarkArray[indexPath.row] = changeBool(value: checkMarkArray[indexPath.row]) UserDefaults.standard.set(checkMarkArray, forKey: "checkmarkarray") self.tableView.reloadData() } override func viewWillAppear(_ animated: Bool) { self.tableView.reloadData() } func changeBool(value: Bool) -> Bool { if value == true { return false } else { return true } } }
hameji001

2018/12/20 05:31 編集

1回目の起動でUserDefaults.standard.array(forKey: "checkmarkarray")を呼び出しているのですが、その際にまだ無いものなので、エラーが起きていると思われます。 実行してみると、found nilと書いてあると思います。 空を見つけましたっていうことです。 なので、エラーが起きる以降を以下のように修正ください ``` if UserDefaults.standard.array(forKey: "checkmarkarray") == nil { for _ in 0 ... itemArray.count - 1 { checkMarkArray.append(false) } UserDefaults.standard.set(checkMarkArray, forKey: "checkmarkarray") } else { checkMarkArray = UserDefaults.standard.array(forKey: "checkmarkarray") as! [Bool] } ```
hik_

2018/12/24 06:50

ご返信ありがとうございます。また返信が遅れすみません。 修正してみます。ありがとうございます。
hik_

2018/12/27 14:44

修正してみたのですが、先日と同様の場所(checkMarkArray = UserDefaults.standard.array(forKey: "checkmarkarray") as! [Bool]) に Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional valueとエラーが出てしまいます。ご返信頂けますと幸いです。 import UIKit class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource { let itemArray: [String] = ["いちご", "バナナ", "りんご"] var checkMarkArray: [Bool] = [] @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() // エラーが起きる checkMarkArray = UserDefaults.standard.array(forKey: "checkmarkarray") as! [Bool] if UserDefaults.standard.array(forKey: "checkmarkarray") == nil { for _ in 0 ... itemArray.count - 1 { checkMarkArray.append(false) } UserDefaults.standard.set(checkMarkArray, forKey: "checkmarkarray") } else { checkMarkArray = UserDefaults.standard.array(forKey: "checkmarkarray") as! [Bool] } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return itemArray.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel!.text = itemArray[indexPath.row] if checkMarkArray[indexPath.row] == true { cell.accessoryType = .checkmark } return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { checkMarkArray[indexPath.row] = changeBool(value: checkMarkArray[indexPath.row]) UserDefaults.standard.set(checkMarkArray, forKey: "checkmarkarray") self.tableView.reloadData() } override func viewWillAppear(_ animated: Bool) { self.tableView.reloadData() } func changeBool(value: Bool) -> Bool { if value == true { return false } else { return true } } }
guest

0

遅くなりました。何度もすいません。
修正しましたので、これで大丈夫です。丸々下のコードに置き換えてください。
2箇所修正しています。

一つはエラーの起こるとこです。
そのコードは不要なので削除しました。

もう一つはcellforRowのとこで、
条件分岐の逆の方、つまりcheckMarkArrayがfalseの時に、
cellのチェックマークなし(.none)に生成し直すというコードが抜けてました。
これではいくら押してデータ自体は変更されていても、
チェックマークが以前のままで消えない状態でした。

コードがきちんと動くことも確認できております。

tableviewZcontroller.swift

1import UIKit 2 3class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 4 5 @IBOutlet weak var tableView: UITableView! 6 7 let itemArray: [String] = ["いちご", "バナナ", "りんご"] 8 var checkMarkArray: [Bool] = [] 9 10 override func viewDidLoad() { 11 super.viewDidLoad() 12 13 if UserDefaults.standard.array(forKey: "checkmarkarray") == nil { 14 for _ in 0 ... itemArray.count - 1 { 15 checkMarkArray.append(false) 16 } 17 UserDefaults.standard.set(checkMarkArray, forKey: "checkmarkarray") 18 } else { 19 checkMarkArray = UserDefaults.standard.array(forKey: "checkmarkarray") as! [Bool] 20 } 21 22 23 24 } 25 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 26 return itemArray.count 27 } 28 29 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 30 let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) 31 32 cell.textLabel!.text = itemArray[indexPath.row] 33 if checkMarkArray[indexPath.row] == true { 34 cell.accessoryType = .checkmark 35 } else { 36 cell.accessoryType = .none 37 } 38 return cell 39 40 } 41 42 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 43 checkMarkArray[indexPath.row] = changeBool(value: checkMarkArray[indexPath.row]) 44 UserDefaults.standard.set(checkMarkArray, forKey: "checkmarkarray") 45 self.tableView.reloadData() 46 } 47 48 override func viewWillAppear(_ animated: Bool) { 49 self.tableView.reloadData() 50 } 51 52 53 func changeBool(value: Bool) -> Bool { 54 if value == true { 55 return false 56 } else { 57 return true 58 } 59 } 60}

投稿2018/12/30 01:54

編集2018/12/30 01:55
hameji001

総合スコア639

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

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

hik_

2018/12/30 01:58

いえいえ、こちらこそ何度も質問に答えてくださり、ありがとうございます。 実装してみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問