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

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

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

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

Q&A

解決済

1回答

1393閲覧

【Swift】各セルに配置した各チェックボタンの状態をそれぞれuser defaultsに保存する方法についての質問

shimishin

総合スコア12

Swift

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

0グッド

1クリップ

投稿2020/04/08 07:17

編集2020/04/08 09:41

前提・実現したいこと

Swiftにて開発をしている初心者エンジニアです。
チェックボックスの状態をボタンの数だけforkeyを作って、userdefaultsに保存したいと考えています。

①xibファイルで作ったセルの中にUIボタン(チェックボタン)を配置。

②webから受け取ったjsonファイルの中にあるWP記事の数だけ、tableViewでセルを作る。

③セルの数だけボタンができる。

④チェックボタンを実現するための、画像を出し入れするクラス作成(該当のソースコード)。
↓(⑤で詰まっています。)
⑤各セルのチェックボタンの状態をuser defaultsに登録したい。

「forkeyに入れる部分を変数にしてfor文で回すのかな」ということを考えつきましたが、
具体的な書き方がわからずに詰まってしまったので、質問させていただきました。
わかりにくい質問で申し訳ありませんが、教えて頂けると助かります。

該当のソースコード

Swift5

1import Foundation 2import UIKit 3 4//ボタンの画像を出し入れするためのクラス 5class CheckButton: UIButton { 6 7 //チェックされていない状態の画像(b-check1)とチェックされた後の画像(b-check2) 8 let checkedImage = UIImage(named: "b-check2")! as UIImage 9 let uncheckedImage = UIImage(named: "b-check1")! as UIImage 10 let ud = UserDefaults.standard 11 var status = "checkStatus" 12 13 14 // Bool property 15 var isChecked: Bool = false { 16 didSet{ 17 if isChecked == true { 18 self.setImage(checkedImage, for: UIControl.State.normal) 19 } else { 20 self.setImage(uncheckedImage, for: UIControl.State.normal) 21 } 22 //ボタンの状態を保存するudをセット。 23 ud.set(isChecked, forKey: status) 24 25 } 26 } 27 28 override func awakeFromNib() { 29 self.addTarget(self, action:#selector(buttonClicked(sender:)), for: UIControl.Event.touchUpInside) 30 31 self.isChecked = ud.bool(forKey: status) 32 33 } 34 35 36 @objc func buttonClicked(sender: UIButton) { 37 if sender == self { 38 isChecked = !isChecked 39 } 40 } 41 42 43 44} 45

該当のソースコードで起きること

①チェックボタンを一つタップする。

②アプリをタスクキルする。

③タップしたチェックボタンの状態が、全ボタンに反映されてしまう。

原因

全ボタンとforkeyがユニークでないためだと考えられる。

補足情報

xcodeのバージョン:11.1
swift5

要領の悪い伝え方となっているかもしれませんが、
何卒よろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

私見なので、これが一般的な意見とは違うかもしれませんが。

swiftではチェックボックス(チェックリスト?)はUITableViewで作らせようとしてるのかなと感じてます。

こんなかんじ↓
イメージ説明

この場合のチェック済みセルの情報(IndexPathの配列)はindexPathForSelectedRowsというUITableViewのプロパティがもってるので、その配列をUserDefaultで読み書きしてあげればいいですね。

UITableViewを実装するという手間が余計にかかりますが、後の管理はUITableViewがよしなにやってくれますので、なれてしまえば、この方法が楽かな〜と個人的には思ってます。

もちろんリストの数が少なければUIButtonのisSelectedで実現してもいいのでしょうが、

UITableViewの方は一度実装してしまえばリスト項目数の増減など融通が聞きますので。


質問が編集されましたので、追記。

↓こんなのに各々の記事を突っ込んでおいて

swift

1struct Article { 2 title: String = "" 3 contents: String = "" 4 isChecked: Bool = false 5} 6 7class ViewController: UIViewController { 8 9// これをtableViewに表示して、でこれを読み書きする感じでしょうかね 10var articles = [Article]() 11

投稿2020/04/08 09:38

編集2020/04/08 10:03
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

shimishin

2020/04/08 12:18

何から何まで甘えてしまう形となってしまうのですが、 セルの中身を決めているコードとtableviewのコードを共有させてください。 ```Swift(セルの中身を決めている) import UIKit class StudyViewCell: UITableViewCell { @IBOutlet var backGround: UIView! @IBOutlet var titleText: UILabel! //チェックボックスをアクション接続 @IBAction func checkView(_ sender: CheckButton) { print(sender.isChecked) } override func awakeFromNib() { super.awakeFromNib() } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state } func setData(t:String,count:Int){ titleText.text = t //セルを交互に白と灰色にする if count % 2 == 0{ backGround.backgroundColor = UIColor.init(red: 1, green: 1, blue: 1, alpha: 1) }else{ backGround.backgroundColor = UIColor.init(red: 243/255, green: 244/255, blue: 243/255, alpha: 0.8) } } } ``` ```Swift(tableView) import UIKit import Alamofire import SwiftyJSON class studyViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var studyView: UITableView! let manaG:Gaksyuu = Gaksyuu.mana let ud = UserDefaults.standard var acsessURLs:[(title:String,url:String)] = [] override func viewDidLoad() { super.viewDidLoad() studyView.dataSource = self studyView.delegate = self let nib = UINib(nibName: "StudyViewCell", bundle:nil) studyView.register(nib,forCellReuseIdentifier: "studyCell") studyView.separatorStyle = .none studyView.sectionHeaderHeight = 10 //networkはadjust(計測ツール)から渡ってくるトラッカーを保存している if(ud.object(forKey: "network") != nil){ getData() }else{ DispatchQueue.main.asyncAfter(deadline: .now()+7){ self.getData() } } } override func viewDidAppear(_ animated: Bool) { navigationController?.setNavigationBarHidden(false, animated: false) navigationController?.navigationBar.topItem?.title = "学習" } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return acsessURLs.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "studyCell", for: indexPath) as! StudyViewCell var title = acsessURLs[indexPath.row].title cell.setData(t: title, count: indexPath.row + 1) return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: false) manaG.strUrl = acsessURLs[indexPath.row].url manaG.title = acsessURLs[indexPath.row].title performSegue(withIdentifier: "studySegue", sender: nil) } // 画面遷移した際 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { let SS: studyContentsView = (segue.destination as? studyContentsView)! SS.url = manaG.strUrl //渡ってきたurlの確認用 print(SS.url) } //JSONを分解 func getData(){ self.acsessURLs.removeAll() //↓設定しないとGET,POSTができない let headers: HTTPHeaders = [ "Content-Type":"application/x-www-form-urlencoded" ] let getDataUrl:String = “記事を受け取るためのURL(ud.object(forKey: "network") as! String)" Alamofire.request(getDataUrl, method:.get, parameters: nil, headers: headers) .responseJSON { response in guard let object = response.result.value else { return } let json = JSON(object) for (i,d) in json{ self.acsessURLs.append(( title: d["title"].string!, url: d["url"].string!)) } self.studyView.reloadData() } } } ``` 上記がセルとtableViewのソースコードです。 丁寧に教えていただいているにも関わらず、未だ解決に至らないので、 もう少しご教授して頂けると幸いです。 お手数をおかけしますが、よろしくお願いいたします。
退会済みユーザー

退会済みユーザー

2020/04/08 12:36

? どういったものが作りたくて、何ができないのでしょうか? 全体をドーン!ではこちらもちょっと困ってしまいます。 セルを選択する方法は、 ・セルのアクセサリでチェックマークをつける(右側レ点) ・編集モードでチェックマークをつける(左側丸チェック) ・セルの背景色で選択されているのを区別する ・UIButtonなどで実装する などなどいくつか方法があるので、どれを選択してして、それを実装する上でなにがわからないかを質問にしてください。
shimishin

2020/04/09 01:30

ご指摘ありがとうございます。 以降気をつけます。 セルを選択する方法については、UIButtonで実装しようと考えていました。 ご教授いただいたindexPathForSelectedRowsを用いて、一度頑張ってみようと思います。 重ね重ね、ご指摘ありがとうございます。
退会済みユーザー

退会済みユーザー

2020/04/09 06:48

indexPathForSelectedRowって書いたのは、質問が編集される前なので、それを保存するという方法はお勧めしませんが。 辞書でデータを持つようなので、そこにisChecked: Boolを足して管理してみたらどうですか
shimishin

2020/04/11 15:32

お返事がおそくなり申し訳ありません。 まだ実現はできていないですが、リストのほうで管理するということを理解できたので、 そちらでやってみようと思います。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問