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

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

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

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

Swift

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

Q&A

解決済

1回答

971閲覧

table viewが未完成の状態でも、完成部分については表示されるようにしたい。

funakenshi

総合スコア1

TableView

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

Swift

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

0グッド

0クリップ

投稿2020/06/10 05:49

table viewが未完成の状態でも、完成部分については表示されるようにしたい。

table view のcellを生成するための処理が重く、全てを完成してから表示するスタイルだと
ユーザーをかなり待たせることになってしまうので、cellが生成し次第、cellを表示するように
したいと思いここ数日作業をしているのですが、うまくいきません。
アドバイスをご教示いただけたらと思います。

ViewController

1 override func viewDidLoad() { 2 super.viewDidLoad() 3 重い処理A() //この重い処理がすべて完了してから、セルが生成されます。 4     tableView.reloadData() 5 } 6 7 8  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 9 return 10 10 } 11 12 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 13 let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) 14    重い処理B()//セルの生成にはこの処理の影響で時間がかかります。 15 return cell 16 } 17 18

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

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

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

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

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

hoshi-takanori

2020/06/10 06:45

重い処理とはどのような性質のものですか? データを用意するのと、それを表示するのと、どちらが重いのでしょうか? 一般論としてはバックグラウンドで処理するとか処理結果をキャッシュするとか一覧画面ではプレビュー的なものを表示して詳細画面で詳しく表示するなどが考えられますが…。
funakenshi

2020/06/10 07:04

コメントありがとうございます。 重い処理Aは、これから表示するコンテンツを特定するためのkeyの一覧の作成処理で、重い処理Bは、重い処理Aによって取得されたkeyを用いて、データをスクレイピングする処理になります。なので、Aの完了がB開始の条件となっています。かかる時間は、Aが15秒、Bが一つのセルあたり5秒くらいだと思います。 Aについてはuserdefaultの活用によりキャッシュが可能ですが、Bに関してはちょっとアイデアが浮かびません。プレビューについても、このviewで情報を得られないとあまり意味がなくなってしまう状況です。 よろしくお願いします。
hoshi-takanori

2020/06/10 07:57 編集

なるほど、それは重そうですね。スクレイピングに関しては、データを取得する部分はバックグラウンドで並行して処理できる (というか、cellForRowAt で実際にデータ取得などの処理を行うのは良くない) と思いますが、タスクを管理するのが面倒でしょうね。頑張ってください。
funakenshi

2020/06/10 15:58

大変貴重なご意見ありがとうございます。 早速、cellForRowAtでのデータ取得処理を他の部位に移動いたしましたところ、 動作が早くなったように感じます。 丁寧なご指摘、ご対応どうもありがとうございました。
guest

回答1

0

ベストアンサー

「重い処理A」でデータを取ってきて、その結果に応じて「重い処理B」を行い、その結果に応じてセルを表示するのであれば、アプリの起動時に「重い処理A」と「重い処理B」を直列に処理し、「重い処理B」が完了し次第 tableView のリロードを行えば良さそうに思います。「重い処理B」は並列化することで、データが収集できたセルから表示させることは可能です。

ただし、厳密にコントロールするのであれば、配列への追加(append)は並列する他のスレッドと競合する可能性も否めないため、排他処理をするなどの必要はあるかと思いますし、データが取得できない時の処理などを考える必要もありそうです(hoshi-takanoriさんがおっしゃっているタスクの管理には、このことも含まれるのではないかと思います)。

また、テーブルセルが全て表示されるまではそれなりの時間がかかるため、UI的にはデータを待っている間は何らかの表示を行う必要もあると思います。

下記は到着したデータだけ逐次表示する例ですが、もちろんセルの数は固定にして表示することもできますし、さほど難しくないのではないでしょうか。

Swift

1import UIKit 2 3class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 4 @IBOutlet weak var tableView: UITableView! 5 var dataArray: [String] = [] 6 7 override func viewDidLoad() { 8 super.viewDidLoad() 9 // Do any additional setup after loading the view. 10 11 // 重い処理Aのつもり。1秒後に処理を完了し重い処理Bを実行する 12 // 実際も重い処理Aは非同期処理にする 13 DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { 14 // 重い処理Bのつもり。ここでは10個の非同期処理を追加している 15 // それぞれ1から5秒後に処理を実行する 16 // 重い処理Bも非同期処理にする 17 for i in 1...10 { 18 DispatchQueue.main.asyncAfter(deadline: .now() + Double.random(in: 1...5)) { 19 // セルに表示するための配列に要素を追加。 20 // もちろん、表示したい内容に応じて適切に変更する。 21 self.dataArray.append("task (i) was finished") 22 // 追加のたびにセルをリロードする 23 self.tableView.reloadData() 24 } 25 } 26 } 27 28 tableView.dataSource = self 29 tableView.delegate = self 30 } 31 32 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 33 // 行数は固定にせず、揃っているデータの数だけにする 34 return dataArray.count 35 } 36 37 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 38 guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") else { 39 return UITableViewCell() 40 } 41 // ここでは表示に特化する 42 cell.textLabel?.text = dataArray[indexPath.row] 43 44 return cell 45 } 46}

投稿2020/06/10 12:35

TsukubaDepot

総合スコア5086

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

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

funakenshi

2020/06/10 18:02

懇切丁寧にご指導いただき、ありがとうございました。 「重い処理B」の並列化について、データの性質上時系列でセルに表示させる必要があったため、 検討いたしましたが、今回は実装を見送る形になりました。 しかし、データソースの作成場所を移動したことにより、処理が大幅にスピードアップし、 標題の一部表示の必要性自体がなくなりそうです。 大変勉強になりました。ありがとうございました。
TsukubaDepot

2020/06/10 21:15

「時系列で表示」というのが具体的にどういう状態なにかわかりませんが、対策としてはいろいろ考えられるかと思います。 並列化したとしても、リロードごとにセルに表示させたい情報をソートするとか、最初からセルだけは作っておき、新しい情報が追加されたらそこだけリロードするなどです。 いずれにせよ、処理が大幅にスピードアップしたということであればよかったかと思います。
funakenshi

2020/06/11 20:07

>>最初からセルだけは作っておき、新しい情報が追加されたらそこだけリロードする このアイデアを使うことで、並列処理化に成功し、セルの生成速度が爆速になりました。 本当に助かりました。お礼申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問