【发布时间】:2019-02-18 05:16:06
【问题描述】:
我的程序是这样构建的:
我有一个UIViewController SingleEventViewController 来布局和处理事件的数据。其中一个元素是 UIView TeilnehmerTableView,其中包含 UITableView participantsTableView。
顾名思义,它用于展示用户,参与活动。首先,我在没有“真实”数据的情况下实现了它。我对用户数组进行了硬编码,并基于它构建了表格视图。这非常有效。
但是由于我实现了 fetchUsers 方法并用该信息填充了数组,所以 tableView 根本不会出现。显然,当我第一次加载页面时它不显示任何内容,因为numberOfRowsInSection 返回 0。但即使在获取之后,当我重新加载 tableview 并且numberOfRowsInSection 返回一个值时,tableview 也是空的。在调试时,我注意到填充单元格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")
}
}
【问题讨论】:
-
是的,在 setupTableView 方法中。
-
请添加您将如何使用 TeilnehmerTableView 的代码
-
不允许更改Datasource和Delegate方法的名称。如果我用我的名字替换 tableview,它会抱怨不符合协议。现在添加代码。
标签: ios swift uitableview uiview cell