Табличные представления "cellForRowAt" никогда не вызываются после добавления реальных данных - PullRequest
0 голосов
/ 13 сентября 2018

Моя программа построена следующим образом:

У меня есть UIViewController SingleEventViewController для разметки и обработки данных события. Одним из его элементов является UIView TeilnehmerTableView с UITableView membersTableView .

Как следует из названия, оно отображает пользователей, участвующих в мероприятии. Сначала я реализовал это без «реальных» данных. Я жестко запрограммировал массив пользователей и создал на его основе табличное представление. Это сработало отлично.

Но поскольку я реализовал метод fetchUsers и заполнил массив этой информацией, tableView вообще не появляется. Очевидно, что при первой загрузке страницы ничего не отображается, потому что numberOfRowsInSection возвращает 0. Но даже после выборки, когда я перезагружаю представление таблицы, а numberOfRowsInSection возвращает значение, представление таблицы пусто. Во время отладки я заметил, что метод заполнения ячеек cellForRowAt никогда не вызывается. Я понятия не имею, что происходит, так как все работало до использования реальных данных.

Может кто-нибудь сказать мне, что происходит?

import UIKit
import Firebase

class TeilnehmerTableView: UIView, UITableViewDelegate, UITableViewDataSource {

var parentVC: SingleEventViewController?
var users = [User]()

let participantsTableView: UITableView = {
    let ctv = UITableView()
    return ctv
}()

override init(frame: CGRect) {
    super.init(frame: frame)
    self.backgroundColor = UIColor.green
    setupTableView()
    setupViews()
    confBounds()
    fetchUsers()
}

func setupTableView() {
    participantsTableView.delegate = self
    participantsTableView.dataSource = self
    participantsTableView.register(TeilnehmerTVCell.self, forCellReuseIdentifier: TeilnehmerTVCell.reuseIdentifier)
    participantsTableView.tintColor = .white
}

func setupViews() {
    addSubview(participantsTableView)
}

func confBounds(){
    participantsTableView.anchor(top: topAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    print("Users: ",users.count)
    return users.count
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    print("heightForRowAt Called")
    return 44
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    print("cellForRowAt Called")
    let row = tableView.dequeueReusableCell(withIdentifier: TeilnehmerTVCell.reuseIdentifier, for: indexPath) as! TeilnehmerTVCell
    row.user = users[indexPath.item]
    return row
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: false)
}

//MARK: - Methods
func fetchUsers() {
    print("Fetching users..")

    let ref = Database.database().reference().child("users")
    ref.observeSingleEvent(of: .value, with: { (snapshot) in
        guard let dictionaries = snapshot.value as? [String: Any] else { return }

        dictionaries.forEach({ (key, value) in

            if key == Auth.auth().currentUser?.uid {
                print("Found myself, omit from list")
                return
            }

            guard let userDictionary = value as? [String: Any] else { return }

            let user = User(uid: key, dictionary: userDictionary)
            self.users.append(user)
        })

        self.users.sort(by: { (u1, u2) -> Bool in
            return u1.username.compare(u2.username) == .orderedAscending
        })
        DispatchQueue.main.async( execute: {
            self.participantsTableView.reloadData()
        })


    }) { (err) in
        print("Failed to fetch users for search:", err)
    }
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

Это код для родителя SingleEventVC :

import UIKit
import MapKit

class SingleEventViewController: UIViewController {

var thisEvent: Event
var eventName: String?
var eventDescription: String?
var eventLocation: CLLocationCoordinate2D?
var eventStartingDate: Date?
var eventFinishingDate: Date?
var eventNeedsApplication: Bool?

let padding: CGFloat = 20

//MARK: - GUI Objects
let scrollView: UIScrollView = {
    let view = UIScrollView()
    return view
}()

let teilnehmerLabel: UILabel = {
    let label = UILabel()
    label.font = UIFont.systemFont(ofSize: 20)
    label.text = "Teilnehmer"
    label.textColor = .black
    return label
}()

let teilnehmerTV: TeilnehmerTableView = {
    let tvt = TeilnehmerTableView()
    tvt.backgroundColor = .brown
    return tvt
}()

let buttonDividerView: UIView = {
    let tdv = UIView()
    tdv.backgroundColor = UIColor.gray
    return tdv
}()

let participateButton: UIButton = {
    let button = UIButton()
    button.backgroundColor = CalendarSettings.Colors.buttonBG
    button.setTitle("Teilnehmen", for: .normal)
    button.setTitleColor(CalendarSettings.Colors.darkRed, for: .normal)
    return button
}()

init(event: Event) {
    thisEvent = event
    super.init(nibName: nil, bundle: nil)
    setupDefaultValues()
}

override func viewDidLoad() {
    super.viewDidLoad()
    applyDefaultValues()
    setupNavBar()
    setupViews()
    confBounds()
    getSnapshotForLocation()
}


//MARK: - Setup
func setupDefaultValues() {
    eventName = thisEvent.eventName
    eventDescription = thisEvent.eventDescription
    eventLocation = thisEvent.eventLocation
    eventStartingDate = thisEvent.eventStartingDate
    eventFinishingDate = thisEvent.eventFinishingDate
    eventNeedsApplication = thisEvent.eventNeedsApplication
}

func applyDefaultValues() {
    titleLabel.text = eventName
    descLabel.text = eventDescription
    if let start = eventStartingDate, let finish = eventFinishingDate {
        timeLabel.text = "Von \(start.getHourAndMinuteAsStringFromDate()) bis \(finish.getHourAndMinuteAsStringFromDate())"
    }

    if let location = eventLocation {
        locationLabel.text = getStringFromLocation(location: location)
        mapLabel.text = getStringFromLocation(location: location)
    }
    if let date = eventStartingDate {
        dateLabel.text = formatDate(date: date)
    }
}

func setupNavBar() {
    self.navigationItem.title = "Event"
}

func setupViews() {
    view.addSubview(scrollView)
    view.addSubview(participateButton)
    participateButton.addTarget(self, action: #selector (buttonClick), for: .touchUpInside)
    view.addSubview(buttonDividerView)

    scrollView.addSubview(teilnehmerLabel)
    scrollView.addSubview(teilnehmerTV)
    teilnehmerTV.parentVC = self
}

func confBounds(){
    let tabbarHeight = self.tabBarController?.tabBar.frame.height ?? 0
    let tableviewHeight: CGFloat = CGFloat(teilnehmerTV.users.count) * 44

    participateButton.anchor(top: nil, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: tabbarHeight, paddingRight: 0, width: 0, height: 50)
    buttonDividerView.anchor(top: nil, left: view.leftAnchor, bottom: participateButton.topAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0.5)

    scrollView.anchor(top: view.topAnchor, left: view.leftAnchor, bottom: buttonDividerView.topAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)



    teilnehmerLabel.anchor(top: descLabel.bottomAnchor, left: view.leftAnchor, bottom: nil, right: view.rightAnchor, paddingTop: 20, paddingLeft: padding, paddingBottom: 0, paddingRight: padding, width: 0, height: 0)
    teilnehmerTV.anchor(top: teilnehmerLabel.bottomAnchor, left: view.leftAnchor, bottom: scrollView.bottomAnchor, right: view.rightAnchor, paddingTop: 5, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: tableviewHeight)
}

override func viewDidLayoutSubviews() {
    let objHeight = titleLabel.frame.height + locationLabel.frame.height + dateLabel.frame.height + timeLabel.frame.height + mapView.frame.height + notizenLabel.frame.height + descLabel.frame.height + teilnehmerLabel.frame.height + teilnehmerTV.frame.height
    let paddingHeight = 10+0+50+padding+20+5 - 15
    print(objHeight, paddingHeight)

    scrollView.contentSize = CGSize(width: view.frame.width, height: objHeight+paddingHeight)
}

//MARK: - Methods
@objc func buttonClick() {
    teilnehmerTV.participantsTableView.reloadData()
    print(teilnehmerTV.participantsTableView.numberOfRows(inSection: 0))
    scrollView.reloadInputViews()
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

1 Ответ

0 голосов
/ 13 сентября 2018

Это потому, что вы не добавили TeilnehmerTableView к представлению в SingleEventViewController, когда делаете запрос на выборку - вы делаете запрос во время инициализации TeilnehmerTableView.Попробуйте позвонить fetchUsers из SingleEventViewController после того, как вы добавили TeilnehmerTableView к представлению;тогда он должен работать.

...