Swift UITableView cellForRowAt indexPath не вызывается для tableView.reloadData () после того, как представление появилось во второй раз - PullRequest
1 голос
/ 30 апреля 2020

Краткое изложение моей проблемы: когда tableView.reloadData() вызывается при локальных изменениях в firestore при первой загрузке представления, оно работает и обновляется, как и положено. Однако после того, как я переключаюсь назад и назад с другими viewControllers, хотя изначально на viewDidAppear() tableView get перезагружается, при локальных изменениях он больше не делает этого.

Я включил более простую версию своего проекта, чтобы лучше объяснить и сделать его воспроизводимым;

Элемент класса

let db = Firestore.firestore()

static var list = [String:[String:Any]]()
static var listenerSet = Bool()
static var listener: ListenerRegistration!

func setListener(completion: @escaping (String) -> Void) {
    if !Item.listenerSet {
        print("Attaching item document listener.")
        Item.listener = db.collection("Items").document("default").addSnapshotListener({ (document, error) in
            let source = document!.metadata.hasPendingWrites ? "Local" : "Server"
            print("Updating item data from the \(source).")
            Item.listenerSet = true
            Item.list = document?.get("List") as! [String:[String:Any]]
            completion("Item data is set")
        })
    } else {
        completion("Item listener already exists")
    }
}

func add(itemID:String) {
    let itemRef = db.collection("Items").document("default")
    itemRef.setData([
        "List": [
            itemID : [
                "Count": FieldValue.increment(1.0),
            ]]
    ], merge:true)
}

FirstViewController: UIViewController

let item = Item()
var itemList = [[String:Any]]()

@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var switchBar: UISegmentedControl!

override func viewDidLoad() {
    super.viewDidLoad()
    // Setting the table views
    tableView.delegate = self
    tableView.dataSource = self
}

override func viewDidAppear(_ animated: Bool) {
    print("View Did appear") // prints OK
    item.setListener() { (result) in
        print(result)
        loadData()
    }
}

func loadData() {
    itemList.removeAll()
    var counter = 0
    for (id,data) in Item.list {
        itemList.append(data)
        itemList[counter]["ID"] = id
        counter += 1
    }
    tableView.reloadData()
}

@IBAction func switchBarChanged(_ sender: UISegmentedControl) {
    let storyBoard = UIStoryboard(name: "Main", bundle: nil)
    switch switchBar.selectedSegmentIndex {
    case 1:
        let vc = storyBoard.instantiateViewController(identifier: "secondViewController")
        show(vc, sender: self)
    default:
        break
    }
}

Расширение FirstViewController: UITableViewDataSource, UITableViewDelegate

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    print("These are items:\(itemList)")
    print(itemList.count)
    print(tableView.bounds.height)
    return itemList.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell") as! ItemCell
    let itemID = itemList[indexPath.row]["ID"] as! String
    let itemName = itemList[indexPath.row]["Name"] as! String
    let itemCount = itemList[indexPath.row]["Count"] as! Double
    cell.itemID = itemID
    cell.itemName.text = itemName
    cell.itemCount.text = String(itemCount)
    print("Items within the tableView \(itemList)") // prints only in the first run whenever there is an upload, or when refreshed.
    return cell
}

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {

    let add = UIContextualAction(style: .normal, title: "Add", handler: { (action, view, completionHandler) in
        item.add(itemID:(itemList[indexPath.row]["ID"] as! String))
        completionHandler(true)
    })

    add.image = UIImage(systemName: "plus")

    let configuration = UISwipeActionsConfiguration(actions: [add])
    configuration.performsFirstActionWithFullSwipe = true
    return configuration
}

Класс ItemCell: UITableViewCell

var itemID = String()
@IBOutlet weak var itemName: UILabel!
@IBOutlet weak var itemCount: UILabel!

SecondViewController: UIViewController

1030 *

Теперь у меня проблема с этим:

  • Приложение загружает, FirstViewController загружает, viewDidAppear запускает. tableView загружает.
  • При смахивании вправо значение на сервере Firestore увеличивается на единицу, включается прослушиватель снимков, перезагружается таблица, и все работает, как и должно быть.
  • После того, как я переключаюсь на SecondViewController и возвращаюсь к FirstViewController viewDidAppear пинает в * 10 45 * загружает.
  • Однако на этот раз, когда я снова проведу пальцем вправо, значение на сервере firestore все еще увеличивается на единицу, и прослушиватель моментальных снимков включается, обновляя Item.list. static var ItemList обновляется, и tableView перезагружается, однако на этот раз работает только метод numberOfRowsInSection, поскольку он печатает счетчик и обновленный itemList, тогда ничего не происходит cellForRowAt не работает и строки не обновляются.
  • Теперь на этом этапе, если я go SecondViewController и возвращаюсь к FirstViewController, строки обновляются, но при пролистывании вправо все равно бесполезно.

Чего мне здесь не хватает? Спасибо всем за ваши ответы.

...