私はアプリケーションでこのバグを修正するために非常識な時間を費やしました。私たちは現在チャットの仕事をしており、テーブルビューを使っています。シンプルなTableView Swiftを使用したセル構築での不思議な動作
メッセージの量が一定量になるまで、テーブルビューは正常に動作します。その後、テーブルがフリックし始めます。私はストーリーボードなしでコード化しました。このため、制約がトラブルの原因であると私は考えました。だから私はchatview tableviewのいくつかの機能を使って、本当にシンプルなtableviewを作ることにしました(実際には、tableviewはcoredataがリンクされていて、たくさんのグラフィックスがあります)。
私は制約があると思っていたので、すべてうまくいくのを見るためにコードを使っていませんでしたが、そうではありませんでした。 gif画像では、2つの望ましくない動作を見ることができます。最初は、テーブルが完全に再生成されることがあるため、非常に短時間でセルが消えて表示されます(これは非常に面倒なフリックの原因となります)。 2番目はそれほど厄介なことではありません。セルは重複しています(これはセルの再利用性機能のためだと思いますが)。短期間でそれらは収容され、すべてがうまく行きます。
https://github.com/hugounavez/pizzaWatch/blob/master/videoBug.gif
IはprepareForReuse()メソッドを追加する試みず、ビューを削除し、再度セルにそれらを作成しますがない結果。
これは、サンプルコードで、あなたは遊び場で問題なくそれをコピーして実行することができます。事前に
//: A UIKit based Playground for presenting user interface
import UIKit
import PlaygroundSupport
class Modelito{
// This is the class tableview model
var celda: String
var valor: String
init(celda: String, valor: String){
self.celda = celda
self.valor = valor
}
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
let tableview: UITableView = {
let table = UITableView()
table.translatesAutoresizingMaskIntoConstraints = false
return table
}()
let button: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Click me to add new cell", for: .normal)
button.setTitle("Click me to add new cell", for: .highlighted)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
var model: [Modelito] = []
let tipoDeCelda = ["MyCustomCell", "MyCustomCell2"]
override func viewDidLoad() {
super.viewDidLoad()
self.setupViews()
self.tableview.register(MyCustomCell.self, forCellReuseIdentifier: "MyCustomCell")
self.tableview.register(MyCustomCell2.self, forCellReuseIdentifier: "MyCustomCell2")
self.tableview.dataSource = self
self.tableview.delegate = self
self.button.addTarget(self, action: #selector(self.addRow), for: .touchUpInside)
// Here I generate semi random info
self.dataGeneration()
}
func setupViews(){
self.view.addSubview(self.tableview)
self.tableview.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
self.tableview.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -50).isActive = true
self.tableview.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 1).isActive = true
self.tableview.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
self.tableview.backgroundColor = .gray
self.view.addSubview(self.button)
self.button.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
self.button.topAnchor.constraint(equalTo: self.tableview.bottomAnchor).isActive = true
self.button.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
self.button.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
self.button.backgroundColor = .orange
}
func dataGeneration(){
let number = 200
// Based in the cell types availables and the senteces, we create random cell info
for _ in 0...number{
self.model.append(
Modelito(celda: tipoDeCelda[Int(arc4random_uniform(UInt32(self.tipoDeCelda.count)))], valor: "\(self.model.count)")
)
}
self.tableview.reloadData()
// After we insert elements in the model we scroll table
let indexPaths: [IndexPath] = [IndexPath(row: self.model.count - 1, section: 0)]
self.tableview.scrollToRow(at: indexPaths[0], at: .bottom, animated: false)
}
@objc func addRow(){
// This function insert a new random element
self.tableview.beginUpdates()
self.model.append(
Modelito(celda: tipoDeCelda[Int(arc4random_uniform(UInt32(self.tipoDeCelda.count)))], valor: "\(self.model.count)")
)
// After inserting the element in the model, we insert it in the tableview
let indexPaths: [IndexPath] = [IndexPath(row: self.model.count - 1, section: 0)]
self.tableview.insertRows(at: indexPaths, with: .none)
self.tableview.endUpdates()
// Finally we scroll to last row
self.tableview.scrollToRow(at: indexPaths[0], at: .bottom, animated: false)
}
}
extension ViewController{
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.model.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 150
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let celldata = self.model[indexPath.row]
switch celldata.celda {
case "MyCustomCell":
let cell = tableview.dequeueReusableCell(withIdentifier: "MyCustomCell", for: indexPath) as! MyCustomCell
cell.myLabel.text = self.model[indexPath.row].valor
return cell
default:
let cell = tableview.dequeueReusableCell(withIdentifier: "MyCustomCell2", for: indexPath) as! MyCustomCell2
cell.myLabel.text = self.model[indexPath.row].valor
return cell
}
}
}
class MyCustomCell: UITableViewCell {
var myLabel = UILabel()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
myLabel.backgroundColor = UIColor.green
self.contentView.addSubview(myLabel)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
myLabel.frame = CGRect(x: 25, y: 0, width: 370, height: 30)
}
}
class MyCustomCell2: UITableViewCell {
var myLabel = UILabel()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
myLabel.backgroundColor = UIColor.yellow
self.contentView.addSubview(myLabel)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
myLabel.frame = CGRect(x: 0, y: 0, width: 370, height: 30)
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = ViewController()
感謝。
編集:
私は遊び場と互換性があるために、@Scriptable解答のコードベースを変更しました。この時点で、重複セルバグは実際にはテーブルビューでは正常であると考え始めています。問題を見るには、ボタンを数回すばやく押す必要があります。
ありがとう@scriptable、私は質問の上記のコードを変更しましたが、私はまだ同じ問題を提示します。実際には、ボタンを非常に短時間でクリックすると問題が表示されます(チャット中で、ルーム参加者がメッセージを非常に速く書く) –
ボタンをすばやく入力していて、1分で約30行追加しました問題はなかった。物理的なデバイスで実行しようとしましたか?シミュレータは実際のデバイスよりも遅く実行できます – Scriptable