Reputation: 37
Can anyone help me get the email
field to display in the tableView
cell? The amount
field is showing up, but I can't get the email
to show along with it.
struct Posts {
var amount:String
var email:String
}
class PaymentRequestVC: UIViewController, UITableViewDelegate {
let tableView = UITableView()
var posts = [Posts]()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
self.tableView.dataSource = self
self.tableView.delegate = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell2")
tableView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: 900)
setupViews()
setupTableView()
loadPosts()
self.tableView.reloadData()
}
func loadPosts() {
let dbUsers = Firestore.firestore().collection("Payouts")
dbUsers.addSnapshotListener { (querySnapshot, error) in
if let error = error {
print("\(error.localizedDescription)")
} else {
for document in (querySnapshot?.documents)! {
if let Amount = document.data()["amount"] as? String {
let Email = document.data()["email"] as? String
print(Amount)
var post = Posts(amount: "", email: "")
post.amount = Amount
post.email = Email ?? ""
self.posts.append(post)
}
}
self.tableView.reloadData()
print(self.posts)
}
}
}
private func setupViews() {
let stackView: UIStackView = {
let sv = UIStackView()
sv.translatesAutoresizingMaskIntoConstraints = false
sv.spacing = 28
sv.axis = .vertical
sv.distribution = .fill
sv.alignment = .fill
return sv
}()
view.addSubview(stackView)
view.addSubview(tableView)
}
func setupTableView() {
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: self.view.topAnchor),
tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor)
])
}
}
extension PaymentRequestVC: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < posts.count {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let post = posts[indexPath.row]
cell.textLabel?.text = post.amount
cell.textLabel?.textColor = UIColor.black
return cell
} else {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath)
let post = posts[indexPath.row]
cell2.detailTextLabel?.text = post.email
cell2.detailTextLabel?.textColor = UIColor.black
return cell2
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80
}
}
Upvotes: 0
Views: 785
Reputation: 161
Swift 5
You need to init the cell with UITableViewCell.CellStyle.subtitle for the detailTextLabel attribute to work.
In your extension, change the cell init:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < posts.count {
let cell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell")
let post = posts[indexPath.row]
cell.textLabel?.text = post.amount
cell.textLabel?.textColor = UIColor.black
cell.detailTextLabel?.text = post.email
cell.detailTextLabel?.textColor = UIColor.black
return cell
} else {
let cell2 = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell2")
let post = posts[indexPath.row]
cell2.detailTextLabel?.text = post.email
cell2.detailTextLabel?.textColor = UIColor.black
return cell2
}
Note that if you want the amount and the mail to both show up, using else will only display either the amount or the email, like in the code below
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < posts.count {
let cell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell")
let post = posts[indexPath.row]
cell.textLabel?.text = post.amount
cell.textLabel?.textColor = UIColor.black
return cell
} else {
let cell2 = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell2")
let post = posts[indexPath.row]
cell2.detailTextLabel?.text = post.email
cell2.detailTextLabel?.textColor = UIColor.black
return cell2
}
So a better approach would be to return both, and else display nothing
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < posts.count {
let cell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell")
let post = posts[indexPath.row]
cell.textLabel?.text = post.amount
cell.textLabel?.textColor = UIColor.black
cell.detailTextLabel?.text = post.email
cell.detailTextLabel?.textColor = UIColor.black
return cell
} else {
let cell2 = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell2")
//Empty cell returned if the condition above is not fulfilled
return cell2
}
Hope this helps.
Upvotes: 1
Reputation: 966
I think your logic in cellForRowAt is incorrect.
You have an array of Posts. And you want to display amount and email in the same cell right? One label being the title and the other being the detailed text.
Both labels are in the same UITableViewCell, so you only need to set it up once per post.
In addition, if indexPath.row is greater than the post count, then posts[indexPath.row] would actually crash your code. So that else statement should actually just log an error or simply do nothing.
Try something like this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < posts.count {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let post = posts[indexPath.row]
cell.textLabel?.text = post.amount
cell.textLabel?.textColor = UIColor.black
cell.textLabel?.detailTextLabel?.text = post.email
cell.textLabel?.detailTextLabel?.textColor = UIColor.black
return cell
} else {
// No cells
}
}
Upvotes: 0