I'm setting up a tableview with customtableview cell, but when i run the app, the data is not shown.
I already check all the connection, identifier, class name, etc
import UIKit
class ViewController: UITableViewController {
#IBOutlet var testingTableView: UITableView!
var data = ["Indomie","Kacang Tanah","Soya"]
override func viewDidLoad() {
super.viewDidLoad()
testingTableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "customCell")
// Do any additional setup after loading the view.
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = testingTableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! customTableViewCell
cell.customLabel.text = data[indexPath.row]
return cell
}
override func numberOfSections(in tableView: UITableView) -> Int {
return data.count
}
}
This is my code for the table view, it's should call the cellforrowat but it's not
You are missing tableView(_:numberOfRowsInSection:) implementation.
You have number of data.count section, but each section has 0 row.
Try replacing numberOfSections(in:) to tableView(_:numberOfRowsInSection:)
I guess you need additional code as below-
testingTableView.delegate = self
testingTableView.datasource = self
testingTableView.reloadData() // I think you missed it!
1). Add this line
#IBOutlet var testingTableView: UITableView! {
didSet {
testingTableView.delegate = self
testingTableView.dataSource = self
}
}
2). You also can add this feature via Stroyboard. Click on your table and using right click drag the pointer on ViewController and add delegate and dataSource.
And i think you missed
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 0 //As per your need.
}
You are using the wrong API, numberOfSections returns the number of sections but you have to return the number of rows
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { {
return data.count
}
There is no need to override numberOfRowsInSection, the default value is 1.
And delete
#IBOutlet var testingTableView: UITableView!
There is an implicit tableView property of UITableViewController
Related
I'm stuck with the following, any inputs would be highly appreciated.
My app has a UITableViewController with custom cells. Let's name its UITableView as TABLE VIEW-1. I am using XIB as its custom cell. Inside that xib, there is another UITableView, (TABLE VIEW-2), with another XIB as its custom cell.
My question is, How can I reload cells of (TABLE VIEW-2) from (TABLE VIEW-1) once I get data from an API in (TABLE VIEW-1). I want to use delegate and protocols to do this.
OR, What would be the correct way of performing this and how would I go about it?
Create a reference of TableView1 in the TableView2 ViewController. You can do this by
-- Open the Assistant Editor
-- Right-click and drag from your UI element (i.e. label) to the code file
-- Xcode auto inserts code for you to create the name and connection
Then call tableView2.reloadData(), where tableView2 is the name of the outlet you just created.
Create a reference of the TABLE VIEW-2 in the TABLE VIEW-1 custom cell (TABLE VIEW-1 CELL)
Create a method inside TABLE VIEW-1 CELL to reload its data alone with the TABLE VIEW-2 (Optional but useful to organize your code)
Inside the tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell of the TABLE VIEW-1 call reload function
class ViewController: UIViewController {
#IBOutlet weak var mainTable: UITableView!
let sampleData = [
(section: "News", SubSections: [
"Breaking news",
"Current Affairs",
"Local"
]) ]
override func viewDidLoad() {
super.viewDidLoad()
self.mainTable.estimatedRowHeight = 200
self.mainTable.rowHeight = UITableView.automaticDimension
let nib: UINib = UINib(nibName: String(describing: MainCell.self), bundle: Bundle.main)
self.mainTable.register(nib, forCellReuseIdentifier: String(describing: MainCell.self))
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
self.sampleData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: MainCell = tableView.dequeueReusableCell(withIdentifier: String(describing: MainCell.self), for: indexPath) as! MainCell
let sectionData = self.sampleData[indexPath.row]
cell.setUpData(title: sectionData.section, data: sectionData.SubSections)
return cell
}
}
class MainCell: UITableViewCell {
#IBOutlet weak var sectionTitle: UILabel!
#IBOutlet weak var internalTable: UITableView!
var tableData:[String]?
override func awakeFromNib() {
super.awakeFromNib()
self.internalTable.estimatedRowHeight = 200
self.internalTable.rowHeight = UITableView.automaticDimension
let nib: UINib = UINib(nibName: String(describing: InsideCell.self), bundle: Bundle.main)
self.internalTable.register(nib, forCellReuseIdentifier: String(describing: InsideCell.self))
}
func setUpData(title: String, data:[String]) {
self.sectionTitle.text = title
self.tableData = data
self.internalTable.reloadData()
}
}
extension MainCell: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
self.tableData?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: InsideCell = tableView.dequeueReusableCell(withIdentifier: String(describing: InsideCell.self), for: indexPath) as! InsideCell
if let subSectionData = self.tableData?[indexPath.row] {
cell.subSectionTitle.text = subSectionData
}
return cell
}
}
class InsideCell: UITableViewCell {
#IBOutlet weak var subSectionTitle: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
I've created a ViewController with my Storyboard linked to it. I've done this before and it has worked fine. This time tho, when I use almost the exact same code for the table view and the table view cell, it returns a nil error when running. I am not sure what the reason exactly is.
//
// IngView1.swift
// Fake
//
// Created by Ian Dong on 11/16/20.
//
import UIKit
class IngView1: UIViewController, UITableViewDataSource {
#IBOutlet weak var display: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
display.dataSource = self
}
var data = ["Oil 5","Beef 3","Chicken 5","Potato 4","Cheese 3","Fish 3","Cabage 4"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "IngReUse")! // Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
let text = data[indexPath.row]
cell.textLabel?.text = text
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
}
Are you sure you properly set prototype cell's identifier? You can do this in the storyboard.
Or if you're not using prototype cell, you can register it in code
display.register(UITableViewCell.self, forCellReuseIdentifier: "IngReUse")
I am using a Custom TableViewCell in TableViewController.
Even the data is getting populated but my TableViewCell does not display it.
Here is my Custom TableViewCell Code
class PlaceItemCellCustom: UITableViewCell {
#IBOutlet weak var placeFace: UILabel?
#IBOutlet weak var placeName: UILabel?
override func awakeFromNib() {
super.awakeFromNib()
}
}
Here is my TableViewContoller
class PlaceListViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
loadListFromSource()
}
// Other code
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return places.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let place = places[indexPath.row]
// I am getting the data
print(place.placeName?.description ?? " " )
let customCell = tableView.dequeueReusableCell(withIdentifier: "PlaceListIdentifier", for: indexPath) as! PlaceItemCellCustom
customCell.placeName?.text = place.placeName
return customCell
}
}
What am I missing here? I am new to IOS app development.
Found similar questions but did not help
Edit: It was working fine for the default TableViewCell.
But when I changed it to custom TableViewCell it does not work. I have set the class name in the storyboard as well.
Here is my Storyboard
Here is the output
As much as I can understand you must have forgotten to connect the IBOutlet of placeName in PlaceItemCellCustom:
In your PlaceItemCellCustom keep placeName as :
#IBOutlet weak var placeName: UILabel!
and in cellForRowAt:
customCell.placeName.text = place.placeName
in this way if you forgot to connect segue Xcode will throw error as :
Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
You can read more about it here :
https://cocoacasts.com/should-outlets-be-optionals-or-implicitly-unwrapped-optionals
You need using this method for get data.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return places.count
}
I am trying to get my tableView to show content in its cells, but it doesn't and I don't know why.
Here is the code. I also have connected the table view to the viewcontroller through dataSource and delegate in the storyboard, so that's why there are not typed in the viewDidLoad() method.
class ViewController: UIViewController, MKMapViewDelegate, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
wordsArray = [Words(sectionName: "Example section", usedWords: ["aaaaa", "aaaaa", "aaaaa"])]
tableView.alpha = 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return favCapitals.count
}
struct Words {
var sectionName: String! = ""
var usedWords: [String]! = []
}
var wordsArray: [Words] = []
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
cell.textLabel?.text = wordsArray[indexPath.section].usedWords[indexPath.row]
cell.textLabel?.textColor = .black
return cell
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let sectionName = "Favourite Capitals"
return sectionName
}
You will need to call the following methods before it listens to cellForRowAt:
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
another common problem is that the frame of the table is not set (e.g. inside a UITableViewCell, with automatic dimensions). The table requires a frame before it gets cells.
You can use tableView.reloadData() in the viewDidLoad Method.
I have a feedVC which shows updates from all user. I'm retrieving data from firebase and want the height to set automatically depending on the post length. the problem is, even after returning UITableViewAutomaticDimension from heightForRowAt, the cells don't resize automatically when the VC is first launched. if I navigate to other vc and come back to the feedVc it is working fine. Images Attached
When VC is launched for the first time
After switching to another VC from tabbar and then again tapping on feed, it's giving the desired results.
class FeedViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var tableviewFeed: UITableView!
var listPost = [Posts]()
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listPost.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableviewFeed.dequeueReusableCell(withIdentifier: "feedCell") as! FeedCell
cell.lblUser.sizeToFit()
cell.lblPost.sizeToFit()
cell.lblUser.text = listPost[indexPath.row].user
cell.lblPost.text = listPost[indexPath.row].post
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
tableviewFeed.estimatedRowHeight = 100
}
override func viewWillAppear(_ animated: Bool) {
FirebaseService.instance.retrievePost { (post) in
self.listPost = post.reversed()
self.tableviewFeed.reloadData()
}
}
}
You need to call
cell.lblUser.layoutIfNeeded()
after
cell.lblUser.sizeToFit()