For a project, I've three UITableViews in an UITabbarController. The initial view loads the tableview correctly, but when I tap on the second tab, the table loads the right amount of cells and the right cell class, but don't show the content on it.
I logged the method tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) and every cell gets the right string values.
This is the code I use:
import UIKit
import RealmSwift
class Hapjes: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tabel: UITableView!
let realm = try! Realm()
let productArray = try! Realm().objects(Product).filter("categorie = 1")
override func viewDidLoad() {
super.viewDidLoad()
tabel.dataSource = self
tabel.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Hapjes"
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return productArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ProductenCellHapjes", forIndexPath: indexPath) as! ProductenCell
var object = productArray[indexPath.row]
cell.label.text = object.valueForKey("productNaam") as! String
cell.plaatje.image = UIImage(named: "1449032338_news.png")
let tmp = object.valueForKey("productNaam") as! String
print("Hapje: \(tmp)")
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
}
ProductenCell.swift:
import UIKit
class ProductenCell: UITableViewCell {
#IBOutlet weak var plaatje: UIImageView!
#IBOutlet weak var label: UILabel!
}
This is the screenshot of the UI how it goes now:
http://i.stack.imgur.com/Gx0Jw.png
Thanks for your help.
Related
Im trying to load a array of strings in a table view but the view does not recognize the array.
I have an array called Playlists (declared as global on ThirdViewController) with objects from class Playlist. When I use it on every other table view I can access every object and use it on the table view (I'm using it on ThirdViewController), but on AddToPlaylist view I can't use it. I think I'm using correctly the cells and func for table views.
This happens when I press the button "AƱadir" on player view. It should load the table view with the array info.
Here is the project (develop branch): tree/develop
import UIKit
class AddToPlaylist: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var myTableViewPlaylist: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Playlists.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "hola", for: indexPath)
cell.textLabel?.text = Playlists[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
Playlists[indexPath.row].songs.append(songName)
performSegue(withIdentifier: "addedSong", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
myTableViewPlaylist.delegate = self
myTableViewPlaylist.dataSource = self
myTableViewPlaylist.reloadData()
}
}
Here is the declaration of Playlists array:
import UIKit
import AVFoundation
var favorites:[String] = []
var Playlists:[Playlist] = []
var selecPlaylist = 0
var firstOpen2 = true
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) {
selecPlaylist = indexPath.row
performSegue(withIdentifier: "segue", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
myTableView2.delegate = self
myTableView2.dataSource = self
if firstOpen2{
crear()
firstOpen2 = false
}
myTableView2.reloadData()
}
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!)
let pl2 = Playlist(name: "Prueba2")
pl2?.addSong(song: songs[1])
Playlists.append(pl2!)
}
}
let cell = tableView.dequeueReusableCell(withIdentifier: "yourIdentifier") as! UITableViewCell
cell.textLabel?.text = Playlists[indexPath.row].name
return cell
Everything works, except when I click on a row.. nothing happens it should output You selected cell number:
class JokesController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var jokes_list: UITableView!
var CountCells = 0
var CellsData = [[String: Any]]()
override func viewDidLoad() {
super.viewDidLoad();
Alamofire.request("http://localhost:8080/jokes.php").responseJSON{ response in
if let JSON = response.result.value as? [[String: Any]] {
self.CellsData = JSON
self.CountCells = JSON.count
self.jokes_list.reloadData()
}else{
debugPrint("failed")
}
}
// 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 numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return CellsData.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
cell.textLabel?.text = CellsData[indexPath.row]["title"] as! String?
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
debugPrint("You selected cell number: \(indexPath.row)!")
}
}
First, you need to inherit from UITableViewDelegate (class ... : UIViewController, UITableViewDelegate.. ).
Then, you need to assign
self.jokes_list.delegate = self
self.jokes_list.dataSource = self
tentatively in your viewDidLoad.
Edit: As #zsteed mentioned.
I am trying to use tableview with delegate methods.
But it is not working.
My class:
class IsteklerTVVC: UITableViewController {
#IBOutlet var mainTable: UITableView!
let missionControl = MissionControl.sharedInstance
var yardimList:[YardimIstek] = [YardimIstek]()
override func viewDidLoad() {
super.viewDidLoad()
mainTable.delegate=self
mainTable.dataSource=self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
veriGetir()
}
func veriGetir() {
let parameters: Parameters = [
"uid": missionControl.id
]
Alamofire.request("domain.com", method: .post, parameters: parameters).responseJSON { response in
print("istek eklendi \(parameters)")
let json = JSON(response.result.value)
for (key,subJson):(String, JSON) in json {
print(subJson[0]["tarih"].string)
let blok=YardimIstek()
blok.id=0
blok.isim="Name"
blok.tarih=subJson[0]["tarih"].string!
blok.lat=subJson[0]["lat"].string!
blok.long=subJson[0]["long"].string!
self.yardimList.append(blok)
}
DispatchQueue.main.async {
self.mainTable.reloadData()
print("ok \(self.yardimList.count)")
}
}
}
let textCellIdentifier = "mainCell"
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return yardimList.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: isteklerCell = tableView.dequeueReusableCell(withIdentifier: textCellIdentifier) as! isteklerCell
let row = indexPath.row
let blok=yardimList[row]
cell.setCell(blok: blok)
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}
}
class isteklerCell: UITableViewCell {
#IBOutlet weak var isimSoyisim: UILabel!
#IBOutlet weak var zaman: UILabel!
func setCell(blok: YardimIstek) {
isimSoyisim.text=blok.isim
zaman.text=blok.tarih
}
}
The problem is, no delegate methods are getting called. I think there is a problem with names. Because when I was using Swift 2, I used the tableview's outlet name as "tableView" and it was working well. Now Swift 3 is not allowing that naming.
So my tableview is looking empty even there is data in yardimList dictionary.
How can I resolve this?
Your delegate function signatures are wrong. They were updated with swift 3:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
Two things to check:
First one is do you need the mainTable property? UITableViewControllers comes with a UITableView property called tableView. If you don't need 'mainTable', you can just replace it with tableView.
Second, if you do need mainTable, then you need to make sure you connected the #IBOutlet to the UITableView you want to use.
Here is the code from my custom cell class:
import UIKit
class CustomOrderTableViewCell: UITableViewCell {
#IBOutlet var MealName: UILabel!
#IBOutlet var MealPrice: UILabel!
#IBOutlet var MealDescription: 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
}
#IBAction func deleteMeal(sender: AnyObject) {
}
}
Here are the table view related functions:
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mealArray.orderedMeals.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("in")
var cell = tableView.dequeueReusableCellWithIdentifier("orderCell", forIndexPath: indexPath) as! CustomOrderTableViewCell
cell.MealName.text = mealArray.orderedMeals[indexPath.row].mealName
cell.MealDescription.text = mealArray.orderedMeals[indexPath.row].mealDescription
let price = NSString(format: "%.2f", mealArray.orderedMeals[indexPath.row].mealPrice) as String
cell.MealPrice.text = "R" + price
return cell
}
The problem is that nothing gets displayed in the table view and func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell is never called.
Any solutions? Thanks
If func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell is never called that means you have not connected your UITableViewDataSource in IB correctly. Make sure that you connect the dataSource property with your ViewController. Also check that all classes are set for your ViewController, TableView and the Cell itself as this another common mistake.
This is a fairly simple question I think. I've separated my UITableView delegate / data sources into their own extensions
//MARK: - UITableView Data Source/Delegate
extension TweetsViewController: UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! TweetCell
return cell
}
}
However in the view controller itself I need to set the tblView delegate
class TweetsViewController : UIViewController {
#IBOutlet weak var tblView: UITableView!
var fetchedResultsController : NSFetchedResultsController!
//MARK: View Management
override func viewDidLoad() {
super.viewDidLoad()
tblView.dataSource = self
}
}
However, since the view controller is nor conforming to the protocols but having the extensions handle them, then how do I explicitly set the datasource and delegate for the tableView? Thanks!
You can divide in a extension, as you can check in the apple documentation section about Extensions handling Protocols.
Here I have implement a minimum code doing what you ask, check it out.
import UIKit
class TableViewViewController: UIViewController {
#IBOutlet weak var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
table.delegate = self
table.dataSource = self
}
}
extension TableViewViewController: UITableViewDelegate,UITableViewDataSource {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
cell.textLabel!.text = "it works"
return cell
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
}
In Swift 3 and above the table view datasource and delegate methods changed.
import UIKit
class HomeViewController: UIViewController {
#IBOutlet var tblPropertyList: UITableView!
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tblPropertyList.delegate = self
tblPropertyList.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
// MARK: - Table View DataSource
extension HomeViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath as IndexPath)
cell.textLabel!.text = "\(indexPath.row) - Its working"
return cell
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
}
// MARK: - Table View Delegate
extension HomeViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let indexPath = tableView.indexPathForSelectedRow
let currentCell = tableView.cellForRow(at: indexPath!)!
print(currentCell.textLabel!.text!)
}
}
the view controller is nor conforming to the protocols but having the extensions handle them
This is incorrect. The extension makes the view controller conformant to the protocols, and the data source and delegate can be set as usual, e.g.: self.tableView.delegate = self
Now in Swift 5.1 you don't need to inherit UITableViewDelegate and UITableViewDataSource
extension HomeViewController {
// MARK: - Table View DataSource
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath as IndexPath)
cell.textLabel!.text = "\(indexPath.row) - Its working"
return cell
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
}
// MARK: - Table View Delegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let indexPath = tableView.indexPathForSelectedRow
let currentCell = tableView.cellForRow(at: indexPath!)!
print(currentCell.textLabel!.text!)
}
}