I'm trying to have a better understanding on how the dataSource and delegate outlets get connected to the UITableView under the hood when you do the connection through the UI in Xcode by dragging and dropping to the viewController icon.
I found this thread but I think I'm missing something because I cannot make it work.
Here is the code I currently have that works fine by connecting the outlets through XCode (by drag and dropping).
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var hobbies:[String] = ["Computers", "Photography", "Cars", "Reading", "Learning New Things"]
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return hobbies.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = hobbies[indexPath.row]
return cell
}
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.
}
}
I tried removing the outlet connections made by XCode, created an outlet for the tableView (myTable) and added the following code in the viewDidLoad method but it doesn't work, no error it just doesn't load the data.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
myTable.delegate = self
myTable.dataSource = self
}
Can someone describe the steps needed to do this connection with code?
Just for reference here are the steps needed to do your connection programmatically.
1.- Create outlet for tableView
#IBOutlet weak var myTable: UITableView!
2.- Assign delegate and dataSource in the viewDidLoad method.
myTable.delegate = self
myTable.dataSource = self
3.- DONE
There are a couple of ways to do it.
1. The simplest one is by dragging and dropping:
In your main.storyboard select your TableView;
Press your Control button;
Click and drag the mouse from your TableView to your ViewController's icon and drop it;
Then select dataSource and delegate as shown on the image above.
2. The other way is by coding:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
}
PS: Make sure not to forget connecting your tableView outlet to your code by dragging and dropping it into your ViewController class.
PPS: It'll also ask you to implement the following methods into your class so that your tableView works properly:
numberOfRowsInSection
cellForRowAtIndexPath
For those who don't have them yet, you'll see Xcode complaining about it.
Related
I need to load all the names of the playlists on the thirdviewcontroller with a table view but it doesn't work.
I'm trying to show a table view on the third view controller with all the names of the playlists that have been created (I create an array with elements of the class playlist, created by myself). On the view did load func I have created two playlists but when I try the app the names don´t show up on the table view.
I have tried to rewrite the code, link the table view again and create the view again, but it does not work. It also does not show any type of failure or closes the app unexpectedly.
I'm new to Swift so I do not know if I'll be doing something more wrong.
Here is the project (develop branch): tree/develop
//
// ThirdViewController.swift
// reproductor
//
// Created by Macosx on 24/4/19.
// Copyright © 2019 mamechapa. All rights reserved.
//
import UIKit
import AVFoundation
var favorites:[String] = []
var Playlists:[Playlist] = []
class ThirdViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var myTableView2: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(Playlists.count)
return Playlists.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = Playlists[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//
}
override func viewDidLoad() {
print("viewdidload")
super.viewDidLoad()
crear()
myTableView2.reloadData()
print(Playlists[1].name)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func crear(){
let pl1 = Playlist(name: "Prueba")
pl1?.addSong(song: songs[0])
Playlists.append(pl1!)
print(Playlists[0].name)
print(Playlists[0].songs[0])
let pl2 = Playlist(name: "Prueba2")
pl2?.addSong(song: songs[1])
Playlists.append(pl2!)
print(Playlists[1].name)
print(Playlists[1].songs[0])
}
}
What is your data is your dataSource, and what to show is your delegate. You have to set your datasource and delegate. You have to set tableView dataSource and Delegate
myTableView2.delegate = self
myTableView2.dataSource = self
What is delegate
UITableViewDelegate
UITableViewDataSource
Set Delegate and DataSource to myTableView2 So add below two lines in viewDidLoad function and than reload myTableView2.
myTableView2.delegate = self
myTableView2.dataSource = self
Downloaded your code from the given github location.
It works fine at my end. Below is the image:
BTW nice songs!!!
You need to set UITableViews’s delegate and data source equal to self.
myTableView2.delegate = self;
myTableView2.dataSource = self;
Do this in viewDidLoad() after super.viewDidLoad().
i'm trying to implement the following design with MapBox and a TableView.
I've been thinking about it and I wanted to use a UITableView for the results, but as far as I know, it's only possible to have data and detail on the left & right side. Is there an alternative to UITableView ?
If not, i'm also facing the problem that my "root"-View is a MapView (from MapBox) and that I can't use the MapViewController as UITableViewController nor as UITableViewDelegate/UITableViewDataSource. Is it possible to Embed the MapView in another View ?
If you need any more information, just let me know. And thank you in advance.
but as far as I know, it's only possible to have data and detail on the left & right side. Is there an alternative
You know wrong. You can include any interface you want in a table view cell. Just make this a custom cell and design it as desired.
Assuming that you have a UIViewController in your storyboard or xib called ViewController which has both a UITableView and an MKMapView (or whatever you are using) correctly connected to the two outlets in the code below:
import UIKit
import MapKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Now tell the system that we are going to reference our
// hand-made table cell from a xib called "MyCell"
self.tableView.register(UINib(nibName: "MyCell", bundle: nil), forCellReuseIdentifier: "MyCell")
// These next you can do here, or in IB...
self.tableView.dataSource = self
self.tableView.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: - TableViewDataSource
// ANY ViewController can do this, if we register the class as conforming
// to the `UITableViewDataSource` protocol
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Get a reference to an instance of our very own UITableViewCell subclass,
// Which we registered in `viewDidLoad`
let c = self.tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! MyCell
// Whatever controls/outlets we have put in our cell subclass,
// we need to populate with data now... (I just did a label)
c.cellNumber?.text = "\(indexPath.row)"
return c
}
//MARK: - TableViewDelegate
//... implement whatever funcs you need ...
//MARK: - MKMapViewDelegate
//... implement whatever funcs you need ...
}
You then need to create the following code, AND a stand-alone xib (called in this case "MyCell.xib"). The xib should contain all of the controls you want in your table cell. In my example it has only one control, the UILabel referenced as cellNumber.
To make the xib, choose "File->New File->User Interface->Empty" from the Xcode menu, then drop a UITableViewCell into the xib from the palette. Make sure you change the class of the cell from UITableViewCell to MyCell. Add whatever controls (and constraints between them) that you need. Obviously, connect all of your controls to relevant #IBOutlets in this class.
class MyCell: UITableViewCell {
// Create `#IBOutlet weak var ...` for all of the controls in your cell here
#IBOutlet weak var cellNumber: UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.configureCell()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.configureCell()
}
func configureCell() {
// Your stuff to load up the IBOutlet controls of your cell with defaults.
// You will be able to override these when the instantiated cell is passed to
// `tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell`
// in the `UITableViewDataSource`
}
}
As I run the code I am successfully feeding JSON data into my application at the rendering of this associated UIView. I have a tableView adequately linked to this file, when I run the application I see the tableview itself. BUT none of the 3 datasource functions are automatically getting called - the 'wtf' print statement, after 2 hours of playing with this, will.not.print.
am I missing something? This code is identical to all other tableviewdatasource code I've written and this simply won't work or render the JSON data I am supplying it with
does anyone have thoughts or suggestions? Thanks!
import UIKit
class ChooseUserViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var users: [BackendlessUser] = []
override func viewDidLoad() {
super.viewDidLoad()
loadUsers()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: UITableViewDataSource
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("wtf")
return users.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("chooseCell", forIndexPath: indexPath)
let user = users[indexPath.row]
print("wtf!")
cell.textLabel?.text = user.email
return cell
}
}
You have tableview with datasource and delegate connected with view controller in storyboard(Interface Builder).
In case you're forgotten to set the dataSource and delegate in your Storyboard using Ctrl+Drag you need to specify in your viewDidLoad that you're the dataSource and delegate like in the following way:
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
loadUsers()
}
I hope this help you.
The Answer: I had not connected the delegate and the datasource of my table object to the view controller - OOPS! I feel silly but that was clearly my issue
I took an UIViewController. Then brought a TableView into it. And then a TableViewCell in the tableview. I assigned identifier and custom table view cell class with that prototype cell. Also created necessary outlets. Then this is my parent view controller:
class MyViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var theTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// let cell = MyTableViewCell()
// cell.optionText = UILabel()
// cell.optionText?.text = "testing..."
// theTableView.addSubview(cell)
theTableView.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
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) as! MyTableViewCell
cell.optionText.text = "hello..."
return cell
}
}
But my table is empty. What am I missing?
You have to add the following line in your viewDidLoad:
theTableView.dataSource = self
When you do that, you provide dataSource to your Tableview from your ViewController and then your TableView starts showing data.
The methods cellForRowAtIndexPath and rowsForSection are both Datasource methods. Since you haven't set your dataSource that's why your TableView fails to load the provided data.
Also if you haven't added the TableView via Storyboard/Xib, you also have to add it as a subview of your view.
I am new to Swift, and iOS development in general. I am attempting to create a custom UITableViewCell. I have created the cell in my main storyboard on top of a UITableView that is inside a UIViewController. When I loaded one of the default cells, I was able to populate it with data. However, now that I am using a custom cell, I cannot get any data to appear in the table. I have gone through all kinds of tutorials and questions posted on the internet, but I can't figure out why it is not working. Any help would be appreciated.
Here is my code for the UIViewController that the tableview resides in.
import UIKit
class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tblView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//self.tblView.registerClass(UITableViewCell.self, forCellReuseIdentifier : "Cell")
self.tblView.registerClass(CustomTableViewCell.self, forCellReuseIdentifier : "Cell")
tblView!.delegate = self
tblView!.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataMgr.data.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : CustomTableViewCell = self.tblView.dequeueReusableCellWithIdentifier("Cell", forIndexPath : indexPath) as! CustomTableViewCell
var values = dataMgr.data[indexPath.row]
cell.newTotalLabel?.text = "\(values.newTotal)"
cell.winLoseValueLabel?.text = "\(values.newTotal - values.currentTotal)"
cell.dateLabel?.text = "5/17/2015"
return cell
}
}
I have stepped through the program where it is assigning values to the cell variables. The variable 'values' is being populated with data, but when stepping over the assignment lines to the cell variables, I found that they are never assigned. They all remain nil.
When you make a custom cell in the storyboard, don't register the class (or anything else). Just be sure to give the cell the same identifier in the storyboard that you pass to dequeueReusableCellWithIdentifier:forIndexPath:.