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

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

ただいまの
回答率

88.20%

複数選択したTableViewのCellのデータを計算した結果を表示したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,048

Jonny_dayo

score 43

前提・実現したいこと

TableViewにJSONデータを表示しています。
名前・数量・単位・値段を表示しているのですが、その中の値段だけを計算して原価計と書いてる場所に結果を表示させたいです。
イメージ説明

cell選択時のコード

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

                  cell?.accessoryType = .checkmark
               //まずgenkaTotalにpriceArrayを表示させる?
         //priceArrayをInt型に変える
            //選択したcellのpriceArrayをgenkaTotalに足していく
      }

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

                  cell?.accessoryType = .none
          //priceArrayをInt型に変える
                //選択したcellのpriceArrayをgenkaTotalから引いていく
      }

JSONデータ

      func getData(){
      let text = "https://script.google.com/macros/s/AKfycbw1IzuulWfaxTtgsNS9Yi5iUNeBqBHy1XC-wV0IOBiAjpzsw98/exec"
      let url = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
            AF.request(url!, method: .get, parameters: nil, encoding: JSONEncoding.default).responseJSON { (response) in
                switch response.result{
                case .success:
                      // 通信成功時
                      guard let data = response.data else {
                          return
                      }

          do {
           let googleData = try JSONDecoder().decode([GoogleData].self, from: response.data!)

                        googleData.forEach { item in
                            self.nameArray.append(item.name)
                            self.amountArray.append("\(item.amount)")
                            self.taniArray.append(item.tani)
                            self.priceArray.append("\(item.price)")
                         }
                      } catch let error {
                          // JSON -> GoogleData にデコード失敗
                          print(error)
                      }
                case .failure(let error):
                      // 通信の失敗
                      print(error)
                }
                self.tableView.reloadData()
            }

    }

試したこと

原価計に文字を表示させたかったので、

genkaTotal.text = cell.priceArray[indexPath].text
と書いてみたのですが、

Value of type 'UITableViewCell?' has no member 'priceArray'


と出てしまいました。配列を取り出して、Int型に変換する方法がわかりません…
変換できたらそれをselectedで判断して合計値出すのかな?と思ってますが合ってるのでしょうか…

ツールのバージョン

Xcode : Version 11.0
Swift : Apple Swift version 5.1

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • t_obara

    2019/10/02 12:20

    cellではなく、selfなのでは?

    キャンセル

  • Jonny_dayo

    2019/10/02 12:25

    確かに!?と思って、genkaTotal.text = self.priceArray[indexPath].textとしてみたのですが、
    Cannot subscript a value of type '[String]' with an argument of type 'IndexPath'
    と出てしまいました…

    キャンセル

  • t_obara

    2019/10/02 12:50

    それはちょっと調べれば出てくるでしょう。indexPathの扱いは基本です。

    キャンセル

  • Jonny_dayo

    2019/10/02 13:06

    あっあっ! genkaTotal.text = self.priceArray[indexPath.row]ですね!!!
    ありがとうございます!!
    とりあえず選択したcellの値段を表示することができました!助かりましたありがとうございます!

    キャンセル

回答 1

checkベストアンサー

+1

UITableView自体の複数選択機能をオンにしているんですよね?

だったら
UITableViewのindexPathsForSelectedRowsを使えば、選択しているセルのIndexPath一覧が取れますので、
選択状態が変わったタイミングで、毎回合計値を算出しなおせばOKです。

メンバー変数に合計値を持っておいて、セルのタップによってその合計値を足したり減らしたりするのは、整数だったらまだいいですが、小数などでは誤差がでるので、辞めたほうがいいです。毎回合計値を求める方がたぶん安全です。

また、おそらくセルの数を増やしてスクロールすると、チェックマークとセルの選択が一致しない可能性がありますので、以下のようなコードで選択状態とチェックマークを同期させる必要がありそうです。

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        cell.accessoryType = cell.isSelected ? .checkmark : .none
    }

ちなみにアクセサリータイプで自分でチェックマークを設定しなくても、標準機能としてチェックマークを出すこともできます。
参考:
How to select multiple rows in UITableView in edit mode?


以下、本題とは関係ありませんが、一つの情報は構造体やクラスにまとめるべきです。
例えば「人」の情報として名前と年齢があり、複数人の情報を保持したい場合、
質問者さんは

var name: [String]
var age: [Int]


のように情報を保持していますが、

struct Person {
    var name: String
    var age: Int
}
var persons: [Person]

のように人構造体(または人クラス)の配列として保持するべきです。
この方が構造化されていて人間的に理解しやすいですし後から1人分のデータを取り回しやすい形になっているので、おすすめです。

そもそも[GoogleData]としてパースしているのでしたら、そのまま[GoogleData]型のままメンバーに保持しても良いのでは?とも思います。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/10/02 16:50

    takabosoft様
    回答ありがとうございます!
    共有頂いたURLを元に左側にチェックを付けようとしたところ、側はできたのですが肝心のマークが出てこなくて、苦戦しております…
    が、selectされたかどうかの状態はprintで確認できているので、これも上記で記載頂いたindexPathsForSelectedRowsを使って合計を求めていく感じでしょうか?

    キャンセル

  • 2019/10/02 17:16

    > 側はできたのですが

    側ってなんでしょう?

    > indexPathsForSelectedRowsを使って合計を求めていく感じでしょうか?

    そうです。

    キャンセル

  • 2019/10/02 18:26

    写真を更新させて頂いたのですが、左側に丸があるけど押してもチェックマーク自体は出てこない状況です。

    キャンセル

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

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

関連した質問

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