This question already has an answer here:
How can you provide default implementations for UIPageViewControllerDataSource?
(1 answer)
Closed 6 years ago.
I want to reuse the code below
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return UITableViewCell()
}
I define a protocol :
protocol ConfigDetail: class, UITableViewDataSource{}
extension ConfigDetail{
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return UITableViewCell()
}
}
but when i use the protocol with a UIViewController, it always tells me i did not conform to protocol UITableViewDataSource, or i have to add #objc before my protocol. But i have struct variables defined in my protocol, #objc may not help. Any solutions?
If you want to implement these data source methods and reuse them, just define a data source class that implements them. And then rather than implementing the delegate methods in the view controller, instantiate a data source object, keep a strong reference to it, and specify it as the data source for the table view.
For example:
class DataSource: NSObject, UITableViewDataSource {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
// configure cell here
return cell
}
}
class ViewController: UITableViewController {
let dataSource = DataSource()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = dataSource
}
}
Related
I am not understanding why my app is not compiling. This is the output currently:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var IndexArray = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsinTableView(tableView: UITableView) -> Int {
return IndexArray.count
}
func tableView(tableView: UITableView, tiltleForHeaderInSection section: Int) -> String? {
return IndexArray[section]
}
func sectionIndexTitlesfortableView (tableView: UITableView) -> [String]? {
return IndexArray
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath as IndexPath) as! TableCell
cell.imgPhoto.image = UIImage(named: "charity")
cell.lblUserName.text! = "User Name"
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
}
You are missing to specify a few methods declared in the protocols your class is deriving from.
func tableView(UITableView, cellForRowAt: IndexPath)
Required. Asks the data source for a cell to insert in a particular location of the table view.
func tableView(UITableView, numberOfRowsInSection: Int)
Required. Tells the data source to return the number of rows in a given section of a table view.
At least the two methods above must be declared in your class, otherwise you get the error.
These are just the required methods, but for functioning in the correct way you need to define others. See Apple documentation on UITableViewDataSource protocol
In Swift 3 all method signatures have been changed to:
func numberOfSections(in tableView: UITableView) -> Int { }
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { }
func sectionIndexTitles(for tableView: UITableView) -> [String]? { }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { }
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {}
I'm trying to present an array of names into cells of tableview controller.
Here's the code:
import UIKit
class TableViewController: UITableViewController
{
var names = ["aA", "aB", "cC"]
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return names.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath)
cell.detailTextLabel!.text = names[indexPath.row]
return cell
}
}
When I simulate it, nothing has appeared into the cells!
What's wrong with my Code!
The compiler did not give me any errors.
Update number of sections. Your problem will be solved.
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
I am getting an error when coding, saying
Type "ViewController" does not conform to protocol "UITableViewDataSource"
Can anyone tell what went wrong with this?
import UIKit
class ViewController: UIViewController, UITableViewDataSource{
let devCourses = [
("Math"),
("Science"),
("English"),
("Computer Programming"),
("Physics")]
func numberOfSectionsInTableview(tableview: UITableView)-> Int {
return 1
}
func tableview(tableView: UITableView, numberOfRowsInSection section: Int) ->Int{
return devCourses.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let (courseTitle) = devCourses[indexPath.row]
cell.textLabel?.text = courseTitle
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
This is a common mistake, please make sure you use the correct words. In your case it should be:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return devCourses.count
}
not
func tableview(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return devCourses.count
}
You must use tableView instead of tableview. It is case sensitive
I think you are missing some functions for that are required by the delegate:
The declaration should be changed to include:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
and then you make sure all the required methods for a table are there:
func tableView(tableView:UITableView!, numberOfRowsInSection section:Int) -> Int
and
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
and invoke delegate on ViewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
yourtableview.dataSource = self
// Do any additional setup after loading the view.
}
Hope this helps
why titleForheaderInsection method in different table view controller not work?
I create two table view controllers in one storyboard for my app, with different function, one is SettingsTableViewControlelr, one is CitylistTableViewControlelr, and they should have different section titles.
tableView:titleForHeaderInSection method is used to name section title, but unfortunately only the method in SettingsTableViewControlelr has been appeared correctly in iOS simulator, but the method in CitylistTableViewControlelr is not work, i put a breakpoint on tableView:titleForHeaderInSection method, and find the method even not be called in CitylistTableViewControlelr. Here is my code below:
SettingsTableViewController
import UIKit
class SettingsTableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, titleForHeaderInSection section:Int) -> String? {
switch section{
case 0:
return"Settings"
default:
return nil
}
}
//the "tableView:titleForHeaderInSection" method in class SettingsTableViewController
//is called and section title appears on simulator.
override func tableView(tableView: UITableView,heightForHeaderInSection section:Int) -> CGFloat {
return 44
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("settingsIdentifier", forIndexPath: indexPath) as! UITableViewCell
return cell
}
}
CitylistTableViewControlelr
import UIKit
class CityListTableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(tableView: UITableView, titleForheaderInsection section: Int) -> String? {
switch section {
case 0:
return "Top Cities"
case 1:
return "Other Cities"
default:
return nil
}
}
//Putting a breakpoint here, and find "tableView:titleForHeaderInSection" method in
//CityListTableViewController is not even been called, thus the section titles, "Top Cities" & "Other Cities",
//do not appear in simulator.I have tried to add "override" keyword before the method, but the
//complier report error says "Method does not override any method from its superclass".
override func tableView(tableView: UITableView,heightForHeaderInSection section:Int) -> CGFloat {
return 44
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section{
case 0:
return 12
case 1:
return 15
default:
return 0
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cityListIdentifier", forIndexPath: indexPath) as! UITableViewCell
switch indexPath.section{
case 0:
cell.textLabel!.text=topCitiesList[indexPath.row]
case 1:
cell.textLabel!.text=otherCitiesList[indexPath.row]
default:
cell.textLabel!.text="unknown"
}
return cell
}
}
My questions are:
Why tableView:titleForHeaderInSection method not be called in CityListTableViewController?
How can I correct my code to make the section title appear on simulator/iPhone respectively?
Have a look at the differences between the two:
In the first view controller where it is being called, the function is being declared like this:
override func tableView(tableView: UITableView, titleForHeaderInSection section:Int) -> String? {
switch section{
Whereas in the one it isn't called it is being declared like this:
func tableView(tableView: UITableView, titleForheaderInsection section: Int) -> String? {
switch section {
You are missing the override declaration. Also, you didn't capitalize the "header" in the second declaration (Thanks for pointing that out Jesper).
Trying to conform to UITableViewDataSource and UITableViewDelegate inside a Swift UIViewController subclass.
class GameList: UIViewController {
var aTableView:UITableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
aTableView.delegate = self
aTableView.dataSource = self
self.view.addSubview(aTableView)
//errors on both lines for not conforming
}
}
Docs say you should conform on the class line after the : but that's usually where the superclass goes. Another : doesn't work. Using a comma separated list after the superclass also doesn't work
EDIT:
Also must adopt all required methods of each protocol, which I wasn't initially doing.
You use a comma:
class GameList: UIViewController, UITableViewDelegate, UITableViewDataSource {
// ...
}
But realize that the super class must be the first item in the comma separated list.
If you do not adopt all of the required methods of the protocol there will be a compiler error. You must get all of the required methods!
As XCode6-Beta7 releases,
I noticed the protocol method of UITableViewDataSource changed a little bit and sounded the same conform to protocol error which worked fine in beta6.
These are the required methods to be implemented according to the UITableViewDataSource protocol:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { // insert code}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // insert code
}
You might want to re-check the difference or re-implement the delegate method that you thought you just implement.
You must implement two require methods here:
func tableView(tableView:UITableView!, numberOfRowsInSection section:Int) -> Int {
return 10
}
func tableView(tableView:UITableView!, cellForRowAtIndexPath indexPath:NSIndexPath!) -> UITableViewCell! {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestCell")
cell.text = "Row #\(indexPath.row)"
cell.detailTextLabel.text = "Subtitle #\(indexPath.row)"
return cell
}
Also, it is important to copy all the non optional functions from the Delegate class. Cmd + Click on the UITableViewDatasource
and copy those two definitions as is.
For me in beta7, the UITableViewDatasource has
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
My implementation:
var items = ["Apple", "Pear", "Banana"]
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Default")
cell.textLabel?.text = items[indexPath.row]
cell.detailTextLabel?.text = "Test"
return cell
}
Usee These methods:
There is change in Data source methods-
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
protocol UITableViewDataSource : NSObjectProtocol {
****func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell****
optional func numberOfSectionsInTableView(tableView: UITableView) -> Int // Default is 1 if not implemented
optional func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? // fixed font style. use custom view (UILabel) if you want something different
optional func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String?
// Editing
// Individual rows can opt out of having the -editing property set for them. If not implemented, all rows are assumed to be editable.
optional func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool
// Moving/reordering
// Allows the reorder accessory view to optionally be shown for a particular row. By default, the reorder control will be shown only if the datasource implements -tableView:moveRowAtIndexPath:toIndexPath:
optional func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool
// Index
optional func sectionIndexTitlesForTableView(tableView: UITableView) -> [AnyObject]! // return list of section titles to display in section index view (e.g. "ABCD...Z#")
optional func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int // tell table which section corresponds to section title/index (e.g. "B",1))
// Data manipulation - insert and delete support
// After a row has the minus or plus button invoked (based on the UITableViewCellEditingStyle for the cell), the dataSource must commit the change
// Not called for edit actions using UITableViewRowAction - the action's handler will be invoked instead
optional func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
// Data manipulation - reorder / moving support
optional func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath)
}
Ur code will works!!
This question is already answered but just want to make things a bit more Swifty.
Instead of writing protocols in UITableViewDelegate, UITableViewDataSource you can divide them using extensions this will help in organising the code. Adding protocol conformance is described in this page
for the above question, this can be confirmed to protocol using extension:
class GameList: UIViewController {
var aTableView:UITableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
aTableView.delegate = self
aTableView.dataSource = self
self.view.addSubview(aTableView)
}
}
extension GameList: UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath)
return cell
}
}
extension GameList: UITableViewDelegate{
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Row Clicked at \(indexPath.row)")
}
}