Custom UITableViewCell from nib in Swift

I am trying to create a custom table view cell from the tip. I mean this article here . I ran into two problems.

I created a .xib file with a UITableViewCell object that was ported to it. I created a subclass of UITableViewCell and set it as the cell class, and Cell as the reusable identifier.

 import UIKit class CustomOneCell: UITableViewCell { @IBOutlet weak var middleLabel: UILabel! @IBOutlet weak var leftLabel: UILabel! @IBOutlet weak var rightLabel: UILabel! required init(coder aDecoder: NSCoder!) { super.init(coder: aDecoder) } override init(style: UITableViewCellStyle, reuseIdentifier: String!) { super.init(style: style, reuseIdentifier: reuseIdentifier) } 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 } } 

In the UITableViewController, I have this code,

 import UIKit class ViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate { var items = ["Item 1", "Item2", "Item3", "Item4"] override func viewDidLoad() { super.viewDidLoad() } // MARK: - UITableViewDataSource override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { return items.count } override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { let identifier = "Cell" var cell: CustomOneCell! = tableView.dequeueReusableCellWithIdentifier(identifier) as? CustomOneCell if cell == nil { tableView.registerNib(UINib(nibName: "CustomCellOne", bundle: nil), forCellReuseIdentifier: identifier) cell = tableView.dequeueReusableCellWithIdentifier(identifier) as? CustomOneCell } return cell } } 

This code is error free, but when I run it in the simulator, it looks like this.

enter image description here

In the UITableViewController in the storyboard, I did nothing with the cell. An empty identifier and no subclass. I tried to add the cell id to the prototype cell and run it again, but I get the same result.

Another error that I encountered is when I tried to implement the following method in a UITableViewController.

 override func tableView(tableView: UITableView!, willDisplayCell cell: CustomOneCell!, forRowAtIndexPath indexPath: NSIndexPath!) { cell.middleLabel.text = items[indexPath.row] cell.leftLabel.text = items[indexPath.row] cell.rightLabel.text = items[indexPath.row] } 

As shown in the above article, I changed the form of the cell type of the UITableViewCell type to CustomOneCell , which is my subclass of UITableViewCell. But I get the following error:

Overriding method with the selector 'tableView: willDisplayCell: forRowAtIndexPath:' has an incompatible type '(UITableView !, CustomOneCell !, NSIndexPath!) → ()'

Does anyone know how to resolve these errors? They seemed to work fine in Objective-C.

Thank.

EDIT: I just noticed if I changed the orientation of the simulator to the landscape and returned it to the portrait, the boxes will appear! I still could not understand what was happening. I downloaded the Xcode project here , demonstrating the problem if you have time to quickly browse.

+127
ios uitableview ios8 swift
Aug 28 '14 at 6:05
source share
8 answers

In Swift 5 and iOS 12.2, you should try the following code to solve your problem:

CustomCell.swift

 import UIKit class CustomCell: UITableViewCell { // Link those IBOutlets with the UILabels in your .XIB file @IBOutlet weak var middleLabel: UILabel! @IBOutlet weak var leftLabel: UILabel! @IBOutlet weak var rightLabel: UILabel! } 

TableViewController.swift

 import UIKit class TableViewController: UITableViewController { let items = ["Item 1", "Item2", "Item3", "Item4"] override func viewDidLoad() { super.viewDidLoad() tableView.register(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCell") } // MARK: - UITableViewDataSource override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return items.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell cell.middleLabel.text = items[indexPath.row] cell.leftLabel.text = items[indexPath.row] cell.rightLabel.text = items[indexPath.row] return cell } } 



The image below shows a set of constraints that work with the provided code without any restrictions on the ambiguity message from Xcode:

enter image description here

+190
Aug 28 '14 at 9:19
source share

Here is my approach using Swift 2 and Xcode 7.3. This example will use one ViewController to load two .xib files - one for the UITableView and one for the UITableCellView.

enter image description here

In this example, you can delete the UITableView directly into an empty TableNib .xib file. Inside, set the owner of the file to the ViewController class and use the output to reference the tableView.

enter image description here

and

enter image description here

Now, in your view controller, you can delegate a tableView, as usual, for example

 class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var tableView: UITableView! ... override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. // Table view delegate self.tableView.delegate = self self.tableView.dataSource = self ... 

To create your custom cell, delete the Cell View Table object again in the empty TableCellNib .xib file. This time you don’t need to specify “owner” in the cell’s .xib file, but you need to specify a Custom class and identifier , for example, “TableCellId”,

enter image description here enter image description here

Create your subclass with any points you need, this way

 class TableCell: UITableViewCell { @IBOutlet weak var nameLabel: UILabel! } 

Finally, return to your view controller, you can download and display it all like this.

 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. // First load table nib let bundle = NSBundle(forClass: self.dynamicType) let tableNib = UINib(nibName: "TableNib", bundle: bundle) let tableNibView = tableNib.instantiateWithOwner(self, options: nil)[0] as! UIView // Then delegate the TableView self.tableView.delegate = self self.tableView.dataSource = self // Set resizable table bounds self.tableView.frame = self.view.bounds self.tableView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] // Register table cell class from nib let cellNib = UINib(nibName: "TableCellNib", bundle: bundle) self.tableView.registerNib(cellNib, forCellReuseIdentifier: self.tableCellId) // Display table with custom cells self.view.addSubview(tableNibView) } 

The code shows how you can simply download and display the nib file (table), and the second is to register the tip to use the cell.

Hope this helps !!!

+27
Jun 03 '16 at 10:40
source share

Swift 4

Sign Up Nib

 tblMissions.register(UINib(nibName: "MissionCell", bundle: nil), forCellReuseIdentifier: "MissionCell") 

In TableView DataSource

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: "MissionCell", for: indexPath) as? MissionCell else { return UITableViewCell() } return cell } 
+12
Apr 03 '18 at 10:41
source share

Another method that may work for you (as I do) is to register the class.

Suppose you create a custom tableView as follows:

 class UICustomTableViewCell: UITableViewCell {...} 

Then you can register this cell in any UITableViewController with which you will display it using "registerClass":

 override func viewDidLoad() { super.viewDidLoad() tableView.registerClass(UICustomTableViewCell.self, forCellReuseIdentifier: "UICustomTableViewCellIdentifier") } 

And you can name it as you would expect in a cell method for a row:

 override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("UICustomTableViewCellIdentifier", forIndexPath: indexPath) as! UICustomTableViewCell return cell } 
+3
Jun 17 '16 at 17:20
source share

You have not registered your pen, as shown below:

 tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCell") 
+3
Oct 02 '18 at 10:07
source share

To fix the error "Override method ... has an incompatible type ..." I changed the function declaration to

 override func tableView(tableView: (UITableView!), cellForRowAtIndexPath indexPath: (NSIndexPath!)) -> UITableViewCell {...} 

(was -> UITableViewCell! - with an exclamation mark at the end)

+2
Sep 21 '14 at 19:14
source share

Swift 4.1.2

XIB.

Create ImageCell2.swift

Step 1

 import UIKit class ImageCell2: UITableViewCell { @IBOutlet weak var imgBookLogo: UIImageView! @IBOutlet weak var lblTitle: UILabel! @IBOutlet weak var lblPublisher: UILabel! override func awakeFromNib() { super.awakeFromNib() // Initialization code } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) } } 

step 2. According to the Viewcontroller class

  import UIKit class ImageListVC: UIViewController,UITableViewDataSource,UITableViewDelegate { @IBOutlet weak var tblMainVC: UITableView! var arrBook : [BookItem] = [BookItem]() override func viewDidLoad() { super.viewDidLoad() //Regester Cell self.tblMainVC.register(UINib.init(nibName: "ImageCell2", bundle: nil), forCellReuseIdentifier: "ImageCell2") // Response Call adn Disply Record APIManagerData._APIManagerInstance.getAPIBook { (itemInstance) in self.arrBook = itemInstance.arrItem! self.tblMainVC.reloadData() } } //MARK: DataSource & delegate func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.arrBook.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // [enter image description here][2] let cell = tableView.dequeueReusableCell(withIdentifier: "ImageCell2") as! ImageCell2 cell.lblTitle.text = self.arrBook[indexPath.row].title cell.lblPublisher.text = self.arrBook[indexPath.row].publisher if let authors = self.arrBook[indexPath.row].author { for item in authors{ print(" item \(item)") } } let url = self.arrBook[indexPath.row].imageURL if url == nil { cell.imgBookLogo.kf.setImage(with: URL.init(string: ""), placeholder: UIImage.init(named: "download.jpeg")) } else{ cell.imgBookLogo.kf.setImage(with: URL(string: url!)!, placeholder: UIImage.init(named: "download.jpeg")) } return cell } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 90 } } 
+1
Nov 22 '18 at 11:28
source share

Just take xib with the UITableViewCell class. Set the user interface as required and assign an IBOutlet. Use it in cellForRowAt () of a table view as follows:

 //MARK: - table method func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.arrayFruit.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { var cell:simpleTableViewCell? = tableView.dequeueReusableCell(withIdentifier:"simpleTableViewCell") as? simpleTableViewCell if cell == nil{ tableView.register(UINib.init(nibName: "simpleTableViewCell", bundle: nil), forCellReuseIdentifier: "simpleTableViewCell") let arrNib:Array = Bundle.main.loadNibNamed("simpleTableViewCell",owner: self, options: nil)! cell = arrNib.first as? simpleTableViewCell } cell?.labelName.text = self.arrayFruit[indexPath.row] cell?.imageViewFruit.image = UIImage (named: "fruit_img") return cell! } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 100.0 } 

enter image description here

100% works without problems (verified)

0
Mar 08 '18 at 9:53
source share



All Articles