I have a view controller, in the viewdidload method I call a function to make some calls to retrieve data online.
After I retrieve the data I append them into an array and reload the table view
at first, everything looks great however, when I scroll down I get to see what you see down below.
extension CastTableViewController : UITableViewDelegate, UITableViewDataSource {
func conigure_cast_table () {
castTable.translatesAutoresizingMaskIntoConstraints = false
castTable.delegate = self
castTable.dataSource = self
castTable.register(ActorCell.self, forCellReuseIdentifier: ActorCell.cellid)
view.addSubview(castTable)
castTable.frame = view.bounds
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cast.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = castTable.dequeueReusableCell(withIdentifier: ActorCell.cellid, for: indexPath) as! ActorCell
let name = cast[indexPath.row].name
let character_name = cast[indexPath.row].character
let pic = cast[indexPath.row].picture_path
cell.configure(name: name, charName: character_name, pic_url: pic)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
}
i fixed this by using prepareforreuse
// in the custom cell class
override func prepareForReuse() {
super.prepareForReuse()
for subview in stack.arrangedSubviews {
stack.removeArrangedSubview(subview)
}
actorPic.image = nil
realName.banner_title.text = nil
realName.info.text = nil
character.banner_title.text = nil
character.info.text = nil
}
Related
i have a tableview in a viewcontroller and because i need to reuse most of the code for another table i created an extra class:
class StatisticsViewDelegate: NSObject, UITableViewDelegate, UITableViewDataSource {
var defaultList:[String]
var infolist:[String] = []
var tableView:UITableView
var controller:UIViewController?
init(defaultList:[String], view:UITableView, controller:UIViewController?) {
self.defaultList = defaultList
self.controller = controller
tableView = view
super.init()
tableView.delegate = self
tableView.dataSource = self
loadTable()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return infolist.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "infocell", for: indexPath) as! TableViewCell
// [fill cell]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// [...]
}
func loadTable() {
DispatchQueue.global(qos: .userInitiated).async {
//[...]
// in this case:
self.infolist = self.defaultList
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
}
and in my UITViewController in the viewDidLoad():
delegate = StatisticsViewDelegate(defaultList: defaultList, view: tableView, controller:self)
delegate is a member of the ViewController
now when i run it, the function func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) never gets called. The func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) gets called however(before and after the reload) and returns the correct number(in my case 4). The TableView isn't visible at all. Where is my error?
Maybe you can use the subclassing strategy to resolve your problem. There are many reference passed to your class and if you forgot to clean that up you will be have memory leaks in your hand. So I'll suggest the simple example as below. You can modify as you like and let me know if that was what you are after. If not please pardon me.
//This will be parent class that will handle all table methods, so you need to write only once the delegates and stuffs
class MyCommonTableController: UITableViewController {
var infoList = [String]()
// MARK: - TableView Delegate and Datsource Impl
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return infoList.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 55.0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = infoList[indexPath.row]
return cell
}
}
The first class that is directly subclassing the from above MyCommonTableController
//In here we just have to know the data and set the infoList from parent
class TheTableViewController: MyCommonTableController {
let defaultList = ["Data1","Data2","Data3"] //....etc
override func viewDidLoad() {
super.viewDidLoad()
//this is were I will set those
infoList = defaultList
//reload the table
tableView.reloadData()
}
}
The second class that is directly subclassing the from above MyCommonTableController. Same process goes here
class TheSecondTableViewController: MyCommonTableController {
let defaultList = ["List1","List2","List3"] //....etc
override func viewDidLoad() {
super.viewDidLoad()
//this is were I will set those
infoList = defaultList
//reload the table
tableView.reloadData()
}
}
And now you are not repeating and table methods. You can also get the reference of table and use in your norma table view
#IBOutlet weak var theTable: UITableView!
let defaultList = ["List1","List2","List3"] //....etc
let commonTable = MyCommonTableController()
// MARK: - LifeCycle
override func viewDidLoad() {
super.viewDidLoad()
commonTable.infoList = defaultList
commonTable.tableView = theTable
}
I'm trying to get an input when the user taps on a cell of a UITableView. That's my code:
import UIKit
class TableView: UIViewController, UITableViewDataSource {
public var data = Array<Array<String>>()
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier")!
cell.textLabel?.text = data[indexPath.row][0]
cell.detailTextLabel?.text = data[indexPath.row][1]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("TEST")
}
}
And in ViewController I have:
...
let tvClass = TableView()
override func viewDidLoad() {
super.viewDidLoad()
tvClass.data = [["title", "name"]]
self.tableView.dataSource = tv
self.tableView.alwaysBounceVertical = false
}
...
Why am I not getting "TEST" when I click on a cell?
didSelectRowAt is a method inside UITableViewDelegate so , set table delegate like this in viewDidLoad
self.tableView.delegate = self;
and change class declaration like this
class TableView: UIViewController, UITableViewDataSource , UITableViewDelegate {
The Only missing thing is
TableViewDelegate.
As delegate tells iOS sdk to know that action is being performed.
self.tableView.delegate = self
I have a table view controller in my view controller. When I give it static number of rows and cell for row index method name it shows nothing to me in the table view. I have also reload the table view but it isn't showing I don't know why is it so,
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell (style: .subtitle, reuseIdentifier: "cellID")
let message = messages[indexPath.row]
cell.textLabel?.text = message.text
return cell
}
Recheck if u have set
tableView.delegate = self
tableView.datasource = self
Also put a breakpoint on cellForRowAtIndexpath to check if code runs through the block.
Also Recheck the cellIdentifier (cellID) is correct or not.
class ViewController:UIViewController,UITableViewDataSource,UITableViewDelegate {
//Getting the reference variables of storyboard
#IBOutlet weak var tableView:UITableView!
var messages = [String]()
override func viewDidLoad() {
super.viewDidLoad()
//Add some packages
messages.append("Super")
messages.append("Free ")
messages.append("Miscellaneous")
messages.append("All ")
tableView.datasource = self
tableView.delegate = self
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell (style: .subtitle, reuseIdentifier: "cellID")
let message = messages[indexPath.row]
cell.textLabel?.text = message.text
return cell
}
}
Use this . This one works for me
class yourViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var tableView:UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.datasource = self
tableView.delegate = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell=tableView.dequeueReusableCell(withIdentifier: "cellID",for : indexPath)
let message = messages[indexPath.row]
cell.textLabel?.text = message.text
return (cell)
}
}
The table cells contained in the first view are properly represented, but the table cells contained in the second view do not appear. I can’t understand why.
HelpController.swift
import UIKit
class HelpController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// MARK: - Initialize
#IBOutlet weak var menuTable: UITableView!
let helpMenu = ["a","b","c"]
override func viewDidLoad() {
super.viewDidLoad()
//datasource link
menuTable.delegate = self
menuTable.dataSource = self
self.menuTable?.tableFooterView = UIView()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table View Data Source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return helpMenu.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "HelpMenuCell")
cell.textLabel?.text = helpMenu[indexPath.row]
return cell
}
}
When i check it with print (helpmenu.count), it return 3. It seems to work well until numberOfRowsInSection, but cellForRowAt does not work.
and this is my first view InfosController.swift
// MARK: - Table View Data Source
// get cell count
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if UserDefaults.standard.value(forKey: "userid") != nil {
// sign in state
return memberMenu.count
} else {
// sign out state
return nonMemberMenu.count
}
}
// change cell text
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "InfosMenuCell")
if UserDefaults.standard.value(forKey: "userid") != nil {
// sign in state
cell.textLabel?.text = memberMenu[indexPath.row]
} else {
// sign out state
cell.textLabel?.text = nonMemberMenu[indexPath.row]
}
return cell
}
This is the code included in the first view that works properly. This works well, but I’m confused because it does not work well in the second view(HelpController).
ps.
The problem in HelpController, In controlle self.menuTable?.tableFooterView = UIView()
So if You are having footer view then You need to write the delegate function heightForFooterInSection and viewForFooterInSection
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
}
Make sure below things
Make sure you added Delegate & DataSource to tableView.
Check your helpMenu count is not equal to
Zero.
If numberOfRowsInSection returns Zero, then probably cellForRowAt
indexPath won't call.
Please check the method declaration once the correct syntax is
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell { }
I have an imageView in my custom table view cell. I have multiple images copied to Xcode.
Now I need to display these images in the tableview cell. I have decalared a leaderImage variable in which I have given the image names.
How can I achieve this?
This is what I have:
var leaderImage : [String]!
override func viewDidLoad() {
self.leadername = ["Oomen Chandy","PC.George","Veena George","M.Mukesh"]
self.areaName = ["Puthupally","Poonjar","Thrissur","Kollam"]
self.approvalrate = ["98%","94%","88%","95%"]
self.leaderImage = ["rahul","Anil","Manu",]
leadTableSetup()
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func leadTableSetup(){
LeadTableView.delegate = self
LeadTableView.dataSource = self
self.LeadTableView.register(UINib(nibName: "LeaderBoardTableViewCell", bundle: nil), forCellReuseIdentifier: "leadCell")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return leadername.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "leadCell") as! LeaderBoardTableViewCell
cell.leaderNameLbl.text = leadername[indexPath.row]
cell.areaLbl.text = areaName[indexPath.row]
cell.approvalLabel.text = approvalrate[indexPath.row]
cell.imageView = leaderImage[indexPath.row]
return cell
}
In cell cellForRowAt method
cell.imageView.image = UIImage(named: leaderImage[indexPath.row])
In your self.leadername contains 5 element but rest of all your array contains 4 or 3 element that's why you have problem occur.
To avoid Crash
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return leaderImage.count
}