🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
TableView

TableView(UITableView)とは、リスト形式で表示するコントロールで、ほとんどのアプリに使用されています。画面を「行」に分けて管理し、一般的には各行をタップした際に詳細画面に移動します。

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

解決済

1回答

744閲覧

[Swift]辞書をソートしてTableViewに値を棒グラフのように表したい

vlb

総合スコア109

TableView

TableView(UITableView)とは、リスト形式で表示するコントロールで、ほとんどのアプリに使用されています。画面を「行」に分けて管理し、一般的には各行をタップした際に詳細画面に移動します。

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

投稿2019/09/08 13:03

編集2019/09/11 12:48

アプリの概要

月別の出費額をソートして棒グラフみたいに表したい.

これまでの流れ

写真1のように,Cell__に__Label(青色のやつ)を配置して,コード2の__TableViewCell__に接続した.
そして,コード1のようにコードを書き足し,実行すると写真2のようになった.
(この時,写真4のように__Cell__の高さを高くして,全ての__Cell__が1度に画面に入りきらないようになっている.)
(ソートされているので,上から12月,11月,・・・,2月,1月)

わからないこと

実行した後に,__TableView__をスライドさせたり__更新ボタン__を何回か押すとログ1がログに表示され,写真3のように__Label__の長さが正しく表示されない.
(ソートはされていて,上から12月,11月,・・・,2月,1月 になっている)

考えられること

コード3の部分が多分悪さをしていると思うが,解決方法がわからない.
力をお貸しください.よろしくお願いします.
(実際に試していただければわかりやすいかと思います.)

写真1

イメージ説明

写真2

イメージ説明

写真3

イメージ説明

写真4

イメージ説明

コード1

Swift

1import UIKit 2 3class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 4 5 @IBOutlet weak var tableView: UITableView! 6 7 //月別の出費額 8 var array1: [String: Int] = ["1月":10,"2月":20,"3月":30,"4月":40,"5月":50,"6月":60,"7月":70,"8月":80,"9月":90,"10月":100,"11月":110,"12月":120] 9 //ソートした後の月別の出費額 10 var rank = [(key: String, value: Int)]() 11 //最も出費が多かった月の出費額 12 var rank1Value = Int() 13 14 15 override func viewDidLoad() { 16 super.viewDidLoad() 17 tableView.delegate = self 18 tableView.dataSource = self 19 reloadData() 20 } 21 22 //TableViewを更新する 23 func reloadData() { 24 //ソート 25 self.rank = self.array1.sorted {$0.value > $1.value} 26 //最も出費が多かった月の出費額を取得 27 self.rank1Value = self.rank[0].value 28 self.tableView.reloadData() 29 } 30 31 32 @IBAction func refreshButton(_ sender: Any) { 33 reloadData() 34 } 35 36 37 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 38 return self.rank.count 39 } 40 41 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 42 guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? TableViewCell else { 43 return UITableViewCell() 44 } 45 //月の出費額を取得 46 let value: Int = self.rank[indexPath.row].value 47 //最も出費が多かった月の出費額で割ることで,それに対する割合を求める 48 let ratio = Double(value) / Double(self.rank1Value) 49 let multiplier = CGFloat(ratio) 50 //TabelViewにLabelが収まるように幅を調節 51 let constant = CGFloat(ratio * -70.0) 52 53 DispatchQueue.main.async { 54 //Labelの幅に関する制約(multiplierとconstant)を設定する 55 cell.label.widthAnchor.constraint(equalTo: self.tableView.widthAnchor, multiplier: multiplier, constant: constant).isActive = true 56 } 57 return cell 58 } 59}

コード2

Swift

1import UIKit 2 3class TableViewCell: UITableViewCell { 4 5 @IBOutlet weak var label: UILabel! 6 7 8 override func awakeFromNib() { 9 super.awakeFromNib() 10 } 11 12 override func setSelected(_ selected: Bool, animated: Bool) { 13 super.setSelected(selected, animated: animated) 14 } 15}

ログ1

Swift

12019-09-08 19:45:42.235064+0900 a[10964:357303] [LayoutConstraints] Unable to simultaneously satisfy constraints. 2 Probably at least one of the constraints in the following list is one you don't want. 3 Try this: 4 (1) look at each constraint and try to figure out which you don't expect; 5 (2) find the code that added the unwanted constraint or constraints and fix it. 6( 7 "<NSLayoutConstraint:0x600003929090 UITableView:0x7fe57f86ee00.leading == UILayoutGuide:0x600002376d80'UIViewSafeAreaLayoutGuide'.leading (active)>", 8 "<NSLayoutConstraint:0x600003929270 UITableView:0x7fe57f86ee00.trailing == UILayoutGuide:0x600002376d80'UIViewSafeAreaLayoutGuide'.trailing (active)>", 9 "<NSLayoutConstraint:0x6000039058b0 UILabel:0x7fe57ec17540.width == 0.0833333*UITableView:0x7fe57f86ee00.width - 5.83333 (active)>", 10 "<NSLayoutConstraint:0x60000392cff0 UILabel:0x7fe57ec17540.width == 0.333333*UITableView:0x7fe57f86ee00.width - 23.3333 (active)>", 11 "<NSLayoutConstraint:0x60000392b070 'UIView-Encapsulated-Layout-Width' UIView:0x7fe57ed27f00.width == 320 (active)>", 12 "<NSLayoutConstraint:0x600003929130 'UIViewSafeAreaLayoutGuide-left' H:|-(0)-[UILayoutGuide:0x600002376d80'UIViewSafeAreaLayoutGuide'](LTR) (active, names: '|':UIView:0x7fe57ed27f00 )>", 13 "<NSLayoutConstraint:0x6000039291d0 'UIViewSafeAreaLayoutGuide-right' H:[UILayoutGuide:0x600002376d80'UIViewSafeAreaLayoutGuide']-(0)-|(LTR) (active, names: '|':UIView:0x7fe57ed27f00 )>" 14) 15 16Will attempt to recover by breaking constraint 17<NSLayoutConstraint:0x6000039058b0 UILabel:0x7fe57ec17540.width == 0.0833333*UITableView:0x7fe57f86ee00.width - 5.83333 (active)> 18 19Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. 20The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

コード3

Swift

1cell.label.widthAnchor.constraint(equalTo: self.tableView.widthAnchor, multiplier: multiplier, constant: constant).isActive = true

コード4

Swift

1cell.widthConstraint.constant = cell.bounds.size.width * multiplier + constant

解決方法

k2moonsのアンサーにより解決することができました.

__Label__に__width__に関する制約を設け(Main.Stroybord__上で),@IBOutlet__で__TableViewCell__クラスに接続し,コード3コード4に書き換えることで解決しました.

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

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

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

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

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

guest

回答1

0

ベストアンサー

Xcode10.3, Swift5.1の環境で試してみました。

swift

1 override func viewDidLoad() { 2 super.viewDidLoad() 3 tableView.delegate = self // 抜けてました 4 tableView.dataSource = self // 抜けてました 5 reloadData() 6 }

上記の設定が抜けているくらいで、特に問題はないようでした。ログも出ませんでした。

イメージ説明

func dequeueReusableCell(withIdentifier identifier: String, for indexPath: IndexPath) -> UITableViewCell

func dequeueReusableCell(withIdentifier identifier: String) -> UITableViewCell?

であれば起こりそうですが、ソースコードはそうはなっていません。

問題は2つあって、並び替え順の問題と、ログ1の問題は別のように思われますが、再現しませんでしたので、下記は参考までに書きます。

ログ1は、一度付加したConstraintを何度も上書きしようとして出ているように思います。
例えば、事前にwidthのConstraintを設定し、Constraintの値のみを変更するやり方であれば、ログ1のようにはならないと思います。

swift

1 DispatchQueue.main.async { 2 //Labelの幅に関する制約(multiplierとconstant)を設定する 3 cell.widthConstraint.constant = cell.bounds.size.width * multiplier 4 }

投稿2019/09/08 15:59

k2moons

総合スコア184

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

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

vlb

2019/09/09 13:18

返信ありがとうございます. 言葉足らずでうまく伝えられていませんでした. tableView.delegate = self tableView.dataSource = self につきましては,Main.Storybordでcontrolキーを使用して繋いでいました. 問題のログにつきましては,写真4のようにCellの高さを高くして,全てのCellが1度に画面に入りきらないようになっている状態で下にスクロールし,更新ボタンを押すと写真3のような現象と問題のログが表示されるようになると思います. 質問の方も訂正させていただきましてので,お手数をおかけしますが,以上の内容でお願いできますでしょうか. DispatchQueue.main.async { //Labelの幅に関する制約(multiplierとconstant)を設定する cell.widthConstraint.constant = cell.bounds.size.width * multiplier } の部分につきましては,今から試させていただきます. よろしくお願いします.
k2moons

2019/09/09 13:31

widthConstraintはセルにセットしたConstraintの@IBOutletです。念のため。
k2moons

2019/09/09 14:14 編集

再現しました。 ``` func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? TableViewCell else { return UITableViewCell() } if cell.tag == 0 { cell.tag = indexPath.row + 100 } print("index.row=(indexPath.row), tag=(cell.tag)") ``` というようなコードを入れてみると何が起こっているのかが分かりやすいです。 func dequeueReusableCell(withIdentifier identifier: String, for indexPath: IndexPath) -> UITableViewCell も func dequeueReusableCell(withIdentifier identifier: String) -> UITableViewCell? も 同じ仕様なので、やはり最初に書いたようにConstraintと上記の仕様で発生すると思われます。 UITableViewは隠れたセルを使い回しています。これはメモリーをセル分だけ確保することでテーブルリストが巨大になった場合のメモリー消費を抑制するためです。 print文を見ると消えたセルを使い回していることが分かります。でもなぜ使い回したセルの設定がうまくいかないか。これも最初に書いたように、既に昔のセルにはConstraintがセットされていてそれが有効なためです。 お知らせた方法を使うと、使い回したセルに対して、必要な情報を再セットできるので、うまく行くはずです。
vlb

2019/09/11 12:38

k2moonsさん 貴方の方法を試したところ解決することができました! 最後までお付き合いありがとうございました. 今後ともよろしくお願いします.
vlb

2019/09/11 13:02

コード3をコード4に書き換えることで解決できました.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問