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

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

ただいまの
回答率

87.38%

[xcode]tableviewのタップした状態を保持したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 650

score 44

状況

イメージ説明
選択すると暗くなるTableviewを使っているのですが、アクセサリーで画面移動したり、検索バーを押すと保持状態が消えてセルの色が白に戻ってしまいます…(中では押されている認識になっている)
また、検索バーを押している状態でアクセサリボタンを押すとエラーが出てしまいます…

エラーメッセージ

reason: 'Application tried to present modal view controller on itself. Presenting controller is <UISearchController: 0x7ffec9075200>.'

遷移先の画面
イメージ説明
青くなってる文字を変更して前の画面に戻る処理をする。

コード

    override func viewDidLoad() {
        super.viewDidLoad()

        //searchControllerまとめ
        searchController = UISearchController(searchResultsController: nil)
        searchController.searchResultsUpdater = (self as UISearchResultsUpdating)
        //位置を固定する
        searchController.hidesNavigationBarDuringPresentation = false
        searchController.searchBar.placeholder = "search"
        //フォーカス時に背景色を暗くするか?
        searchController.obscuresBackgroundDuringPresentation = false
        //サイズを調整
        searchController.searchBar.sizeToFit()
        //tableViewのヘッダーにセット
        tableView.tableHeaderView = searchController.searchBar

        //Tableviewまとめ
        tableView.frame = tableViewContainer.bounds
        tableView.delegate = self
        tableView.dataSource = self
        tableView.allowsMultipleSelection = true
        tableViewContainer.addSubview(tableView)

        getData()

        NotificationCenter.default.addObserver(self, selector: #selector(cookingViewController.receivechange(_:)), name: Notification.Name("change"), object: nil)

        searchResults = recipedata.shared.nameArray.enumerated().map { $0.0 }

    }

    @objc func receivechange(_ notification: NSNotification) {
        let amountget = notification.userInfo!["amount"] as! String
        let priceget = notification.userInfo!["price"] as! String
        let cellget = notification.userInfo!["cellindex"] as! Int
        recipedata.shared.amountArray[cellget] = amountget
        recipedata.shared.priceArray[cellget] = priceget

        tableView.reloadData()
    }

    //画面をタップした時
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        baika.resignFirstResponder()
        genkaritsu.resignFirstResponder()

    }
     //文字が入力される度に呼ばれる
    func updateSearchResults(for searchController: UISearchController) {

        if searchController.searchBar.text! == ""{
            searchResults = recipedata.shared.nameArray.enumerated().map { $0.0 }
        }else{
            self.searchResults = recipedata.shared.nameArray.enumerated().filter({
            // 大文字と小文字を区別せずに検索
                $0.1.lowercased().contains(searchController.searchBar.text!.lowercased())
            }).map({ $0.0 })
            }
        self.view.endEditing(true)
        self.tableView.reloadData()

    }

    func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
        searchController.dismiss(animated: true, completion: nil)
        celltaped = searchResults[indexPath.row]
        performSegue(withIdentifier: "edit", sender: nil)
    }
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return searchResults.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "Cell")

        cell.selectionStyle = .blue
        cell.textLabel?.text = recipedata.shared.nameArray[searchResults[indexPath.row]]
        cell.textLabel?.adjustsFontSizeToFitWidth = true
        cell.textLabel?.numberOfLines = 1
        cell.detailTextLabel?.text = recipedata.shared.amountArray[searchResults[indexPath.row]] + recipedata.shared.taniArray[searchResults[indexPath.row]] + "  " + recipedata.shared.priceArray[searchResults[indexPath.row]] + "円"
        cell.detailTextLabel?.adjustsFontSizeToFitWidth = true
        cell.detailTextLabel?.numberOfLines = 1
        cell.accessoryType = .detailButton

        return cell

    }

      func getData(){ //省略
    }

      func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let cell = tableView.cellForRow(at:indexPath)
        print("select - \(indexPath)")

        cell?.isSelected = true

        //totalに入れる
        self.total += Float(recipedata.shared.priceArray[searchResults[indexPath.row]]) ?? 0
        genkaTotal.text = String(self.total)
        //totalをラベルに反映させる
        selectedrecipe.append(indexPath.row)
        if kotei == "baika" {
            BaikaKotei()
        }else{
            GenkaKotei()

        }

    }
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if segue.identifier == "edit" {

          let nextVC = segue.destination as! CellViewController
            nextVC.namevalue = recipedata.shared.nameArray[celltaped]
            nextVC.categoryvalue = recipedata.shared.categoryArray[celltaped]
            nextVC.unitvalue = recipedata.shared.taniArray[celltaped]
            nextVC.amountvalue = recipedata.shared.amountArray[celltaped]
            nextVC.pricevalue = recipedata.shared.priceArray[celltaped]
            nextVC.cellindex = celltaped

        }
    }

    //2回目の選択時
    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath:
        IndexPath) {
        print("deselect - \(indexPath)")

        let cell = tableView.cellForRow(at:indexPath)
            cell?.isSelected = false

            self.total -= Float(recipedata.shared.priceArray[searchResults[indexPath.row]]) ?? 0
            genkaTotal.text = String(self.total)
            if let deselect = selectedrecipe.firstIndex(of: indexPath.row){
            selectedrecipe.remove(at: deselect)
            }

            if kotei == "baika" {
                BaikaKotei()

            }else{
                GenkaKotei()

            }

      }

    @IBAction func save(_ sender: Any) {
        searchController.dismiss(animated: true, completion: nil)

        var alertTextField: UITextField?

        let alert = UIAlertController(
            title: "レシピ名",
            message: "名前をつけて保存",
            preferredStyle: UIAlertController.Style.alert)
                alert.addTextField(
                    configurationHandler: {(textField: UITextField!) in
                    alertTextField = textField
                    })
                    alert.addAction(
                    UIAlertAction(
                        title: "Cancel",
                        style: UIAlertAction.Style.cancel,
                        handler: nil))
                    alert.addAction(
                        UIAlertAction(
                        title: "OK",
                        style: UIAlertAction.Style.default) { _ in
                        if let text = alertTextField?.text {

                            var saver: [String] = UserDefaults.standard.array(forKey: "alert") as? [String] ?? []
                            saver.append(text)
                            UserDefaults.standard.set(saver, forKey: "alert")

                            var baikabox: [String] = UserDefaults.standard.array(forKey: "baikaB") as? [String] ?? []
                            baikabox.append(self.baika.text!)
                            UserDefaults.standard.set(baikabox, forKey: "baikaB")

                            //各々userdefaultに保管

                            var tap: [[Int]] = UserDefaults.standard.array(forKey: "tap") as? [[Int]] ?? []
                            tap.append(self.selectedrecipe)
                            UserDefaults.standard.set(tap, forKey: "tap")

                            }                       
                        }
        )
        self.present(alert, animated: true, completion: nil)
    }
}

誰か助けてください(´;ω;`)

ツールのバージョン

Xcode : Version 11.2.1 Swift : Apple Swift version 5.1

追記

        struct GoogleData: Decodable {
            let name: String
            let amount: String
            let unit: String
            let price: String
            let category: String

            private enum CodingKeys: String, CodingKey {
                case name
                case amount
                case unit
                case price
                case category
            }
        }
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

tableView cellForRowAt indexPath: IndexPath


のところで、他の

cell.textLabel?.text = recipedata.shared.nameArray[searchResults[indexPath.row]]


と同じように、

cell.isSelected =  (true or falseの値を示す変数)


とisSelectedのBool型を設定してあげる必要があります。
なので、メモリ上にBool型の配列が必要になります。

本題とはそれますが、
データ構造が
値段 = [450, 300, 200, 100, 210]
品名 = [カレー, うどん, パン, ジュース, りんご]
となっておりますが、

商品1
name = "カレー"
category = 食べ物
price = 450
unit = "個"
のようにまとめた方が、わかりやすいのではないでしょうか?

下記のように、struct や enumをうまく組み合わせて実現できます。

struct ItemData {
   let name: String
   let category: Category
   let price: Int
   let unit: String
}

enum Category {
   case food
   case drink
}

// データを流し込む時は下記のように
let curry = ItemData(name: "カレー", category: .food, price: 450, unit: "袋")

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/03 15:07

    回答ありがとうございます!
    cell.isSelected = true で試してみたところ、セルが一瞬灰色にぺろぺろするだけでした…
    ここに自分でifこうならTrue、って文に変えたらいける感じですかね…?
    データの構造についてもアドバイスありがとうございます!
    一応追記のように別ファイルは作っているのですが、これとはまた別の話ですかね…?

    キャンセル

  • 2019/12/03 15:14

    struct でデータを定義してあるなら、nameArrayやpriceArrayは不要になり、
    var googleDataArray:[GoogleData] = *******などを宣言し、
    その配列を利用して表示するになると思います。
    また、次のNextViewへもそれぞれの要素を渡さずに、
    GoogleData自体を渡せばいいのではないでしょうか?

    キャンセル

  • 2019/12/03 15:16

    なるほど確かに…( ゚д゚)ハッ!
    面倒なことしてましたね…
    今回の質問の件が解決したら書き直してみます!!

    キャンセル

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

  • ただいまの回答率 87.38%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る