Unable to override UITableView delegate methods in UIViewController
Since you are no longer writing a subclass of UITableViewController
you no longer override its delegate and datasource functions, but you are providing your own implementation to conform to those protocols. Swift strictly checks if the method you are declaring to override is in fact already implemented in the base class. This was true with the UITableViewController
, but it's no longer the case with UIViewController
.
In short: drop the override
keyword from the delegate and dataSource functions.
UITableView delegate and datasource in external class does not work
Your main problem is that TbController() get deallocated. dataSource
and delegate
properties on UITableView are weak. Therefor, because you only assign TbController to a local variable and to the weak properties, it will get deallocated.
Also, the UITableViewController already creates a TableView for you. It is not good practice to "recreate" it. I would rather make use of the TableView in the UITableViewController and add the UITableViewController's view as a subview to your UIViewController's view.
To fix, you need an instance variable for TbController.
Sample code with ivar for TbController and making use of Tbcontroller's UITableView.
import UIKit
class ViewController: UIViewController {
var cont: Tbcontroller = Tbcontroller()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
cont.type = 1
self.view.addSubview(cont.view)
}
}
import UIKit
class Tbcontroller: UITableViewController {
var type:Int = 1
override func viewDidLoad() {
super.viewDidLoad()
tableView.scrollEnabled = false
tableView.separatorStyle = .None
tableView.allowsSelection = true
tableView.userInteractionEnabled = true
self.tableView.delegate = self
self.tableView.dataSource = self
}
func getCell() -> UITableViewCell{
let presentCell: UITableViewCell = UITableViewCell()
return presentCell
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 4
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = getCell()
cell.textLabel?.text = "ciao"
cell.textLabel?.font = UIFont.systemFontOfSize(13)
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("clicked")
}
}
UITableView does not conform to protocol UITableViewDataSource error
You have incorrectly set up your ViewController. Either create a UITableViewController which is just a UITableView, or add a UITableView to a UIViewController (Like you have almost done).
The didSelectRowAt method will allow you to segue to a new viewController, but in my examples only if it is set up correctly in a storyboard.
UITableViewController option
class TableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
// Configure the cell...
return cell
}
// MARK: - Table view delegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
performSegue(withIdentifier: "SegueIdentifier", sender: self)
}
UIViewController option
(The UITableView will need to be added through a Storyboard in this example)
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
// Configure the cell...
return cell
}
// MARK: - Table view delegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
performSegue(withIdentifier: "SegueIdentifier", sender: self)
}
Here is an example project to work from
Can't use UITableViewDataSource with custom cell
Try the opposite:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = BaseCell()
return cell
}
But you probably want to use something like:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("BaseCell") as? BaseCell
return cell!
}
Make sure you set "BaseCell" as your cell identifier, as following:
If you get a runtime error like "Found nil while unwrapping optional", you need to see BaseCell as the class for your cell, see picture:
Swift. Why doesn't work UITableView delegates?
In example you provided they connect delegate
and datasource
of tableView
via Storyboard
not from code .. thats why it confused you .. you have option .. Either you set them in storyboard
or set them in code
...
this is how you can do it in storyboard
.. Control + drag
to controller .. you will get options to check both .. delegate
and dataSource
Related Topics
Problem with Swiftui and Foreach on Xcode Playground
Why Do I Have to Unwrap a Weak Self
Implement a Crosshair Kind Behaviour in Realitykit
Switch Statement Where Value Is Int But Case Can Contain Array
How to Synchronize Access to a Property That Has Didset
Is There an Firebase Realtime Database Equivalent to The Increment Method Available in Firestore
Testing a Class Which Preserves Its State in Private Variables
Core Data with Swiftui Mvvm Feedback
Xcode 9.3 Watchkit Crash on Wkinterfacebutton Tap
Why Swift Disallows Weak Reference for Non-Optional Type
Lldb for Swift: Access Computed Property or Perform Function Call in Type Summary Python Script
Pass and Print All Cases in an Enum in Swift
How to Convert an Array to List in Realm
Swiftui: Make Remaining Area of List Item Detect Clicks
Swiftui Go Back Programmatically from Representable to View