I created a custom class for a cell in my program. When I try to use it in another class to create a cell I keep getting the error Cannot invoke 'init' with an argument list of type '(style: UITableViewCellStyle, reuseIdentifier: StringLiteralConvertible)'. Can anybody point me in the right direction here? I would really appreciate any help. I tried changing the class to inherit form UITableViewController so I can use this var cell: bookCell = self.tableView.dequeueReusableCellWithIdentifier("cell1") as bookCell but it crashes the program if I try to make the class inherit from tableviewcontroller.
import UIKit
class bookCell: UITableViewCell {
#IBOutlet var bookImage: UIImageView!
#IBOutlet var bookDescription: UILabel!
#IBOutlet var bookPosterUsername: UILabel!
}
import UIKit
class SubjectBooksViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var navigationBarTitle: UINavigationBar!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationBarTitle.topItem?.title = "\(selectedCourse)"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell : bookCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "subjectCell")
//var cell: bookCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "subjectCell")
//var cell: bookCell = self.tableView.dequeueReusableCellWithIdentifier("cell1") as bookCell
return cell
}
}
Update code:
import UIKit
class SubjectBooksViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var navigationBarTitle: UINavigationBar!
#IBOutlet var myTableView: UITableView! //Outlet for your table View
override func viewDidLoad() {
super.viewDidLoad()
self.myTableView.dataSource = self //If you have not done in IB
self.myTableView.registerNib(yourCellNib, forCellReuseIdentifier: "subjectCell")
self.navigationBarTitle.topItem?.title = "\(selectedCourse)"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell : bookCell = tableView.dequeueReusableCellWithIdentifier("subjectCell", forIndexPath: indexPath)
return cell
}
}
In viewDidLoad() in line :
self.myTableView.registerNib(yourCellNib, forCellReuseIdentifier: "subjectCell")
replace yourCellNib with loaded nib file for your custom cell.
Registering your nib file is required if you plan to reuse cell in your table view. It is always a good idea to reuse cells.
You need to override this function and get your custom cell in this manner:
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell = tableView.dequeueReusableCellWithIdentifier(
"subjectCell",
forIndexPath: indexPath) as bookCell
Your class name really should be BookCell though, with an uppercase "B". Just to keep with existing standards
Related
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var myTableView: UITableView!{
didSet {
tableView.dataSource = self
//tableView.reloadData()
}
}
var data = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
data = ["data1","data2", "data3"]
//tableView.reloadData()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as UITableViewCell
cell.lbl?.text = data[indexPath.row]
return cell
}
}
you need to set delegate and you have not used code properly.
#IBOutlet var myTableView: UITableView!
var data:[String]!{
didSet {
tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.dataSource = self
tableView.delegate = self
data = ["data1","data2", "data3"]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as UITableViewCell
cell.lbl?.text = data[indexPath.row]
return cell
}
}
Note: if your cell is a nib file then register your cell in viewDidLoad before setting delegate=self
tableView.register(UINib(nibName: "nibname", bundle: nil), forCellReuseIdentifier: "myCell")
To get you going, this is all the code you need:
class MyCell: UITableViewCell {
#IBOutlet var lbl: UILabel!
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var myTableView: UITableView!
var data = [String]()
override func viewDidLoad() {
super.viewDidLoad()
data = ["data1","data2", "data3"]
// set the table view's dataSource
myTableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) as! MyCell
cell.lbl?.text = data[indexPath.row]
return cell
}
}
This assumes that you
created a cell prototype in Storyboard
assigned its Custom Class to MyCell
gave it an identifier of "myCell"
added a label to it and connected it to #IBOutlet var lbl: UILabel!
Move
tableView.dataSource = self
to ViewDidLoad()
And add
tableView.delegate = self
Below dataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
I am working on a todo list app that works with a table view in Swift. The table view has a UILabel called titleLabelOutlet. When I was building the app I got an error that says The titleLabelOutlet outlet from the FirstViewController to the UILabel is invalid. Outlets cannot be connected to repeating content.I have never received this error before. How do I fix it? This is my code:
import UIKit
var phoneNumberList = [String]()
var titleFieldList = [String]()
class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var titleLabelOutlet: UILabel!
#IBOutlet weak var phoneNumberLabelOutlet: UILabel!
#IBOutlet weak var myTableView: UITableView!
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return (phoneNumberList.count)
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
phoneNumberLabelOutlet.text = phoneNumberList[indexPath.row]
titleLabelOutlet.text = titleFieldList[indexPath.row]
return(cell)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
{
if editingStyle == UITableViewCellEditingStyle.delete
{
phoneNumberList.remove(at: indexPath.row)
titleFieldList.remove(at: indexPath.row)
myTableView.reloadData()
}
}
override func viewDidAppear(_ animated: Bool) {
myTableView.reloadData()
}
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.
}
}
Your outlets should be in cell class instead of viewcontroller because labels are inside cell
And in crllfor row at delegate you have to get your outlets like that
`let cell = tableView.dequeueReusableCell(withReuseIdentifier: cellIdentifier", for: indexPath) as! TableViewCellClass
cell.lbloutlet.text = "any text"
return cell
`
Create CustomTableCell subclassing UITableViewCell.
Have Labels in cell and connect to phoneNumberLabelOutlet & titleLabelOutlet in CustomTableCell class.
use CustomTableCell in place UITableViewCell for cellForRowAtIndex function.
now you can set values for labels as
cell.phoneNumberLabelOutlet.text = phoneNumberList[indexPath.row]
cell.titleLabelOutlet.text = titleFieldList[indexPath.row]
So I added a table view to a normal view controller and inside that table view I made a prototype cell. Ive done some work to make the cell appear but it won't. How do I fix this? Here is my code:
import UIKit
class NewsScreenViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var trendingButton: UITabBarItem!
#IBOutlet weak var newestButton: UITabBarItem!
#IBOutlet weak var topJournalists: UITabBarItem!
#IBOutlet weak var tabBar: UITabBar!
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return UITableViewCell()
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
}
You need to return cell after you get the cell and give it something to display. Try something more like this
let fillTableViewArray = [String]()
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReuseableCellWithIdentifier("cell")
//now that you have that cell you have to put something into it. For example an Array of strings, can be used to fill the table view
cell!.textLabel?.text = fillTableViewArray[indexPath.row]
return cell!
}
If you want to do this in the storyboard, you can instead add a label to the prototype cell in the storyboard, set an integer value for the label's tag, and then find the label by adding these two lines after you do let cell = ...
let label = cell.viewWithTag(100) as UILabel!
label.text = fillTableViewArray[indexPath.row]
I hope this helps fix your issue
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.
I'm trying to clean up my crowded ViewController by moving the UITableViewDataSource (and Delegate) to a seperate class.
While the DataSource was inside the ViewController (see just below), it worked fine
class ViewController: UIViewController, UITableViewDataSource{
//MARK: Properties
#IBOutlet weak var myTableView: UITableView!
let cellIdentifier = "myTableViewCell"
let myArray = ["Label one", "Label two", "Label three"]
override func viewDidLoad()
{
super.viewDidLoad()
myTableView.dataSource = self
}
override func didReceiveMemoryWarning()
{super.didReceiveMemoryWarning()}
//MARK: TableViewDataSource
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{return 1}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{return myArray.count}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! myTableViewCell
cell.myLabel.text = myArray[indexPath.row]
return cell
}
}
With The myTableViewCell class
class myTableViewCell: UITableViewCell{
#IBOutlet weak var myLabel: UILabel!
override func awakeFromNib()
{super.awakeFromNib()}
override func setSelected(selected: Bool, animated: Bool)
{super.setSelected(selected, animated: animated)}
}
And this works fine and populates a basic table with the labels filled from the strings in myArray.
However when I move the DataSource to it's own class, as follows, it doesn't work
ViewController
class ViewController: UIViewController
{
//MARK: Properties
#IBOutlet weak var myTableView: UITableView!
override func viewDidLoad()
{
super.viewDidLoad()
myTableView.dataSource = myDataSource()
}
override func didReceiveMemoryWarning()
{super.didReceiveMemoryWarning()}
}
and here's the myDataSource class
class myDataSource: NSObject, UITableViewDataSource
{
let cellIdentifier = "myTableViewCell"
let myArray = ["Label one", "Label two", "Label three"]
//MARK: TableViewDataSource
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{return 1}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{return myArray.count}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! myTableViewCell
cell.myLabel.text = myArray[indexPath.row]
return cell
}
}
(The myTableViewCell remains the same)
This setup just outputs an empty table, even though all I did was copy-paste the code from the ViewController to myDataSource. What am I missing? (aside form the delegate. I'll deal with that later, first I need to find what's the problem with the data source).
I'm a bit of a rookie to swift, so I'm having a really rough time understanding where I'm going wrong here. Any help at all would be greatly appreciated. If you could just remember in your answer that I'm just starting out, so try not to throw too many complicated concepts at me without explaining. Thanks
Probably the code in your data source never gets called because your data source doesn't get retained by the table here myTableView.dataSource = myDataSource() so basically gets released right away. To solve this, keep the data source as a property.
Declare the separate class as an extension of the ViewController class
extension ViewController: UITableViewDataSource
{
let cellIdentifier = "myTableViewCell"
let myArray = ["Label one", "Label two", "Label three"]
//MARK: TableViewDataSource
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{return 1}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{return myArray.count}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! myTableViewCell
cell.myLabel.text = myArray[indexPath.row]
return cell
}
}
I'm using also always delegate methods in an extension declaration but in the same file as the main class