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

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

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

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

Q&A

解決済

1回答

260閲覧

cellにつけたチェックマークをUserDefaultsに保存して、view読み込み時に保存したデータからcellにチェックマークをつけたい

clocker

総合スコア17

Swift

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

0グッド

0クリップ

投稿2018/10/24 01:56

セルを表示してチェックマークをつけることは出来たのですが、そこからチェックマークをつけたセルのIndexPathをUserDefaultsに保存して、view読み込み時に、保存したデータからcellに再びチェックマークをつけることが出来ません。具体的なコードは以下のものです。

//ボタンを押すとチェックマークのついたセルのIndexPathをUserDefaultsに保存 @IBAction func hozon(_ sender: UIBarButtonItem) { for x in 0...Name.count-1 { //Name.countはrowの数 let indexPath: IndexPath = IndexPath(row: x, section: 0) let cell = nameList.cellForRow(at:indexPath) //nameListはTableViewの名前 if cell?.accessoryType == .checkmark { check.append(indexPath) //var check = [IndexPath]() } } //UserDefaultsにcheckの内容を保存 UserDefaults.standard.set(check, forKey: "GroupData") } //読み込み時にUserDefaultsに保存されているデータからセルにチェックをつける override func viewDidLoad() { super.viewDidLoad() //UserDefaultsに保存されていたらIndexPath型で代入 if UserDefaults.standard.object(forKey: "GroupData") != nil{ check = UserDefaults.standard.object(forKey: "GroupData")! as! [IndexPath] //チェック入れる for x in 0...check.count-1 { let indexPath: IndexPath = check[x] let cell = nameList.cellForRow(at:indexPath) cell!.accessoryType = .checkmark } } }

これは初めに表示されるビューコントローラのプログラムではありません。このプログラムのビューコントローラにsegueでジャンプする時にアプリが落ちてしまいます。また上のプログラムでは下から3行目の「let indexPath: IndexPath = check[x]」の行にThread 1: Fatal error: Index out of rangeと表示されているので、試しにそこのfor分全体を消去すればこのビューコントローラにジャンプすることが出来ました。しかしその状態でセルにチェックをつけてhozonボタンを押してもアプリが落ちてしまいます。どこがダメでどう改善すべきか教えていただきたいです。お願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

大前提として、「UITableViewCellは画面に表示されている範囲しか存在しない可能性がある」という事を頭に入れておいてください。

そのため、チェックの状態はメンバー変数等で保持してください。
テーブルからセルの要求が有った時にメンバー変数を元にチェック状態を入れるなりしてください。

投稿2018/10/24 04:57

takabosoft

総合スコア8356

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

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

clocker

2018/10/24 09:04

ご回答ありがとうございます。 チェックの状態はどのようなコードで表すことができるのですか?
takabosoft

2018/10/24 09:56

ちょっと今出先で試せませんがSet<IndexPath>のような集合型を使えば良いかと思います。ただ、UserDefaultsにそのまま保存できるかどうかは忘れました(だめなら一度配列にmapしてから保存/読み込みすればよいかと)
clocker

2018/10/25 02:08

let info = Set<IndexPath>() とすると、どこのセルにチェックが入っているかという情報がinfoに保持されると考えて良いのでしょうか。またそれを再び読み込むんでセルに表示する方法がよく分りません。言葉で教えて頂いてもそれをコードで表す能力がまだ足りないので、具体的なコードも一緒に教えて頂ければ幸いです。
takabosoft

2018/10/25 02:26 編集

letだと変更できないのでvarにしてください。そのような感じでよいです。現在セルの要求をテーブルビューから受け取っている箇所(func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell)でセルを生成(または再利用)して中身をいじっていると思いますが、その中でチェックマークを復元すればいいです。コードは自分で書かないと意味がないのでがんばってください。
clocker

2018/10/25 07:10

コードは頑張って自分で書きます。以下のコードで、どこのセルにチェックが入っているかという情報をinfoに保持、そしてUserDefaultsに保存しようと考えています。しかしhozonボタンを押した途端にアプリが落ちてしまいます。どこがいけないんでしょうか。 @IBAction func hozon(_ sender: UIBarButtonItem) { var info = Set<IndexPath>() //UserDefaultsにinfoの内容を保存 UserDefaults.standard.set(info, forKey: "GroupData") }
takabosoft

2018/10/26 00:30 編集

UserDefaultsのset関数は何でも保存してくれるようなものではなくて、ある程度の型の制限があります。Set型はたしか対応していなかった気がするので、配列に変えてから格納してください(map関数使えばすぐにsetから配列へ変換できます)。UserDefaultsから取得するときも配列型として読み込んだものをSet型に変換してください(Set型のコンストラクタで配列を受け取れたような記憶があります)
clocker

2018/10/26 07:32

下記のコードでチェックマークをつけずにhozonを押すとアプリは落ちませんが、チェックマークをつけてhozonを押すと落ちます。試行錯誤の結果、以下の行 UserDefaults.standard.set(IndexInfo, forKey: "GroupData") //配列型をUserDefaultsに保存 を削除すればチェックをつけていてもアプリは落ちないことが分かりました。この行が悪いんだと思いますが、IndexInfoは配列型なので問題はないと思います。どこに問題がありますか。 @IBAction func hozon(_ sender: UIBarButtonItem) { var info = Set<IndexPath>() //Set型の変数を定義 for x in 0...Name.count-1 { let indexPath: IndexPath = IndexPath(row: x, section: 0) let cell = nameList.cellForRow(at:indexPath) if cell?.accessoryType == .checkmark { //チェックマークがあれば info.insert(indexPath) //Set型の変数infoにindexPathを足していく } } //UserDefaultsにinfoの内容を保存 let IndexInfo:[IndexPath] = info.map{($0)} // Set型から配列に変換 UserDefaults.standard.set(IndexInfo, forKey: "GroupData") //配列型をUserDefaultsに保存 }
takabosoft

2018/10/26 08:56

あ、IndexPath型もUserDefaultsは対応していませんでしたねw IndexPath型は辞書型に変換してみてください。つまり辞書型の配列型を保存すればいけるとおもいます。UserDefaultsで何の型が対応しているかは公式リファレンスを見てみてください。
takabosoft

2018/10/26 09:05 編集

で、二個上のコードではhozon関数内でcell?.accessoryTypeを見ていますが、最初に私が回答したとおり、この考え方は駄目なので、セルをタップした段階でメンバー変数を更新する方式にしてください。(hozon関数を実行したタイミングでは画面外のcellは取得できない可能性が高いため)
clocker

2018/10/27 02:11

rowの数字をInt型の配列にしてUserDefaultsに保存することが出来ました。その配列の数字をIndexPath型のrowに、sectionには0を代入してチェックを付けようと思っています。そのコード(下)を実行すると、またしてもアプリが落ちました。Xcodeを確認すると「order.section = 0」の行で「Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)」が表示されていました。試しに「order.section = 0」の行を消してみると、今度は「order.row = check」の行で同様の表示がありました。なのでIndexPath型への代入が原因だと考えてますが、どうすれば良いでしょうか。 //UserDefaultsに保存されていたら if UserDefaults.standard.object(forKey: "GroupData(GN)") != nil{ var order = IndexPath() check = UserDefaults.standard.object(forKey: "GroupData(GN)")! as! [Int] order.section = 0 for check in check { order.row = check //チェック入れる let cell = nameList.cellForRow(at:order) cell?.accessoryType = .checkmark } }
takabosoft

2018/10/28 03:14

sectionとrowを後から変更しようとすると落ちるようですね。原因は不明ですが、イニシャライザで毎回生成すれば落ちないと思いますので、そちらで回避してください。IndexPath(row: Int, section: Int)
clocker

2018/10/28 07:47

アドバイス有難うございました。おかげでcellにつけたチェックマークをUserDefaultsに保存して、view読み込み時に保存したデータからcellにチェックマークをつけることが出来ました・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問