How to initialize UI things when reuse a UITableViewCell - ios

I want to reuse a UITableViewCell in my app, but I get this error: Unexpectedly found nil while implicitly unwrapping an Optional value.
I find that this is because the UI things in UITableViewCell is nil, so my app crashed.
My UITableViewCell code is like this:
class WordListCell: UITableViewCell {
#IBOutlet weak var wordListCoverImage: UIImageView!
#IBOutlet weak var wordListName: UILabel!
#IBOutlet weak var wordListInfo: UILabel!
var wordList: WordList? {
didSet {
updateUI()
}
}
private func updateUI() {
wordListName.text = wordList?.name
wordListInfo.text = wordList?.description
wordListCoverImage = UIImage()
}
}
I create it in the storyboard and link the outlet to the code in the other TableView.
But this time, I want to reuse the cell in a new TableView which is all created by code, so I don't know how to initialize the UI things.
The new UITableView code is like this:
tableView.delegate = self
tableView.dataSource = self
tableView.register(WordListCell.self, forCellReuseIdentifier: "wordListCell")
//the delegate
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return wordLists.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let wordList = wordLists[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "wordListCell", for: indexPath)
if let wordListCell = cell as? WordListCell {
wordListCell.wordList = wordList
}
return cell
}
Please tell me how to reuse the cell.Thanks!

Okay so I think what you are doing wrong is when you create a custom tableView cell, you are not assigning a UIImage. So instead try doing this wordListCoverImage = UIImage(named: wordList.imageName).
Now also in your tableView class inside viewDidLoad() apart from adding
tableView.delegate = self
tableView.dataSource = self
tableView.register(WordListCell.self, forCellReuseIdentifier: "wordListCell")
Then at let cell = tableView.dequeueReusableCell(withIdentifier: "wordListCell", for: indexPath) downcast it as a custom cell class like so.
let cell = tableView.dequeueReusableCell(withIdentifier: "wordListCell", for: indexPath) as! WordListCell
And then finaly under that set the cell.delegate = self
I hope this helps!

Related

Why is this not displaying information in a UITableView?

I would really appreciate any help on this. I'm very new to coding, and have no luck implementing this feature so far. I'm looking to populate a UITableViewCell with information gathered from Firestore, namely: title, username and content. I've been able to print the 'title' array successfully, but have not been able to actually populate this into the cells.
This is the HomeViewController, where my UITableView is:
class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var logoutButton: UIButton!
var postArray: [String] = []
var documents: [DocumentSnapshot] = []
let db = Firestore.firestore()
let currentUserID = Auth.auth().currentUser?.uid
// Find the UserIDs of people following
// Where Field for those UserIDs in "Posts"
override func viewDidLoad() {
super.viewDidLoad()
getFollowingPosts()
configureTableView()
}
func getFollowingPosts() {
let searchForFollowing = db.collection("users").document(currentUserID!).collection("Following")
searchForFollowing.getDocuments { (snapshot, error) in
for documents in snapshot!.documents {
let followedUID = documents.get("uid")
print(followedUID!)
self.db.collection("posts").whereField("uid", isEqualTo: followedUID!).getDocuments { (querySnapshot, error) in
for documents in querySnapshot!.documents {
let uid = documents.get("uid") as! String
let title = documents.get("Title") as! String
let ProfilePictureURL = documents.get("ProfilePictureURL") as! String
let username = documents.get("username") as! String
let content = documents.get("Content") as! String
self.postArray.append(title)
print(self.postArray)
}
self.tableView.reloadData()
}
}
}
}
func configureTableView() {
tableView.delegate = self
tableView.dataSource = self
tableView.register(PostTableViewCell.self, forCellReuseIdentifier: "PostCell")
// remove separators for empty cells
tableView.tableFooterView = UIView()
// remove separators from cells
tableView.separatorStyle = .none
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
postArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostTableViewCell
let post = postArray[indexPath.row]
return cell
}
}
This is my PostTableViewCell:
class PostTableViewCell: UITableViewCell {
#IBOutlet weak var usernameLabel: UILabel!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var contentLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
addSubview(usernameLabel)
addSubview(titleLabel)
addSubview(contentLabel)
}
}
If anyone could help, this would be massively appreciated. Like I said, I've been struggling a lot with this one.
You don't seem to be setting the data onto anything in the cell.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostTableViewCell
let post = postArray[indexPath.row]
cell.titleLabel.text = post
return cell
}
Also, modify the register method if you're using nib
func configureTableView() {
//...
tableView.register(UINib(nibName: "PostCell", bundle: nil), forCellReuseIdentifier: "PostCell")
//...
}
Note: Make sure that the nib file has nib's identifier set as "PostCell".

How to hide a custom class label in a table view cell?

I have a table view controller with a custom cell and a CustomCell class. The code in the VC looks like this:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Actual", for: indexPath as IndexPath) as! CustomCell
let mySeries = series[indexPath.row] as Series
cell.mySeries = mySeries
return cell
}
The CustomClass code is the following:
class CustomCell: UITableViewCell {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var seasonLabel: UILabel!
#IBOutlet weak var episodeLabel: UILabel!
var mySeries: Series! {
didSet {
nameLabel.text = mySeries.name
seasonLabel.text = mySeries.season
episodeLabel.text = mySeries.episode
}
}
Everything works fine so far. But I made the cells editable and the reordering symbol (three stripes) is now laying over my episodeLabel. So I'd like to hide this label until the editing is done. The editing function for reordering looks like this:
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to toIndexPath:IndexPath) {
let customCell = CustomCell()
customCell.episodeLabel.isHidden = true
let rowToMove = series[fromIndexPath.row]
series.remove(at: fromIndexPath.row)
series.insert(rowToMove, at: toIndexPath.row)
}
This is the part which is working. But when I create an instance of the CustomCell class (customCell) and insert this line in the function above I get an fatal error because nil is found:
customCell.episodeLabel.isHidden = true
Same behavior when I create a function hideEpisodeLabel() in the CustomCell class and call it from the VC. What am I doing wrong?
you must get cell instance in moveRowAt func
let customCell= tableView.cellForRowAtIndexPath(indexPath) as? SeriesCell
customCell.episodeLabel.isHidden = true
}
This additional method hides the label in the desired way:
override func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
let customCell = tableView.cellForRow(at: indexPath) as? CustomCell
customCell?.episodeLabel.isHidden = true
return true
}
To bring the label back I have to reload the table view. This can be done by overriding the setEditing method:
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
if(!editing) {
tableView.reloadData()
}
}
Now, in the 'cellForRowAt indexPath:' method I only have to set the label to: isHidden = false.

Custom Cells Returning Blank in TableView Swift 3

So I am currently trying to populate a tableview with custom cells based on an API call. After I get the data to populate with, I reload the tableview. It has the data based on how many cells it has, but each one is blank. I've looked over some similar problems people had, but can't seem to find the fix. Any help would be great, thank you!
I call my API and collect the data I need. Then I reload the tableview.
class SearchViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tableView: UITableView!
#IBOutlet var typeSwitch: UISegmentedControl!
#IBOutlet var searchBar: UITextField!
var timeoutTracker = 0
var items: [String] = []
var count = 1
func searchCall() {
Alamofire.request("http://www.plex.dev/api/search/" + type + "/" + searchBar.text!).responseJSON { response in
debugPrint(response)
if response.response == nil {
self.timeoutTracker = self.timeoutTracker + 1
if self.timeoutTracker == 5 {
self.timeoutTracker = 0
self.popUp()
}
else {
sleep(2)
self.searchCall()
}
}
if let json = response.result.value {
let jsonTest = JSON(json)
for x in jsonTest["results"] {
if let title = x.1["title"].string {
self.items.append(title)
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.reloadData()
}
}
}
}
}
func tableView(_ tableView:UITableView, numberOfRowsInSection section:Int) -> Int
{
return self.items.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
var cell = self.tableView.dequeueReusableCell(withIdentifier: "cell")! as! MovieCell
cell.movieTitle?.text = self.items[indexPath.row]
cell.moviePoster?.image = #imageLiteral(resourceName: "avatar.png")
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("You selected cell #\(indexPath.row)!")
}
Here is the custom Cell Class
import UIKit
class MovieCell: UITableViewCell {
#IBOutlet var moviePoster: UIImageView!
#IBOutlet var movieTitle: UILabel!
#IBAction func addMovie(_ sender: AnyObject) {
}
}
Here is my storyboard:
And here is my blank tableview:
I hope it isn't something obvious, but thanks for the help either way!
EDIT: changing my identifier to something other than "cell" seemed to do the trick
Are you calling the searchCall() anywhere?
Also would suggest you to declare
tableView.delegate = self
tableView.dataSource = self
in viewDidLoad() of the SearchViewController and add the delegates and datasource of the UITableView as an extension to SearchViewController (it is a better code practice)
EDIT: After looking again at your cellForRowAt: try and replace your code with the following
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! MovieCell
and not use self.tableView here
EDIT 2: Sometimes using the default cell identifier 'cell' can cause some problems, so better to use a different one such as 'movieCell'
I suspect you are registering a class or nib with your table view, but when you use prototype cells you should not do this. Also, you should use the more modern dequeueReusableCell(withIdentifier: String , for indexPath: IndexPath). Also, I would resist the temptation to ever call sleep.
Did you give the class to the cell and connect the outlets in cell

Split View Controller - Custom UITableViewCell

I am trying to add a custom UITableViewCell to my Split View Controller Master. When I run my app the cells don't appear, although they do carry the information as confirmed by a println statement. After some research I found out that only standard UITableViewCells are generated.
The Table ViewController has the Data Source and Delegate connected via the Storyboard and the UITableViewCell has a custom Class with Identifier.
The TableView & TableViewCell are in the same ViewController.
The TableViewCell reusable identifier is "ArtistCell" and it's class is ArtistCell.
import UIKit
import MediaPlayer
class ArtistsMasterTableViewController: UITableViewController, UITableViewDelegate, UITableViewDataSource {
var artistsQuery:MPMediaQuery!
var artists:NSArray!
var artistAlbums:NSArray!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
artistsQuery = MPMediaQuery.artistsQuery()
artists = artistsQuery.collections
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return artists.count
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println(artists[indexPath.row].items)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ArtistCell", forIndexPath: indexPath) as! ArtistCell
cell.backgroundColor = UIColor.clearColor()
var rowItem:MPMediaItem = artists.objectAtIndex(indexPath.row).representativeItem
if let artwork = rowItem.valueForProperty(MPMediaItemPropertyArtwork) as? MPMediaItemArtwork {
cell.artistImage!.image = artwork.imageWithSize(cell.artistImage.bounds.size)
}
cell.artistNameLabel.text = rowItem.valueForProperty(MPMediaItemPropertyArtist) as? String
// artistCell.albumsLabel.text = rowItem.valueForProperty(MPMediaItemPropertyArtist) as? String
// artistCell.songsLabel.text = rowItem.valueForProperty(MPMediaItemPropertyArtist) as? String
return cell
}
The custom cell:
class ArtistCell: UITableViewCell {
#IBOutlet weak var artistImage: UIImageView!
#IBOutlet weak var artistNameLabel: UILabel!
#IBOutlet weak var albumsLabel: UILabel!
#IBOutlet weak var songsLabel: UILabel!
}
Here are some Storyboard screenshots:
Great question. From what I've seen the way to implement this is to create a custom xib file that you dequeue. Here is the best article on the subject in objective-c: https://medium.com/#musawiralishah/creating-custom-uitableviewcell-using-nib-xib-files-in-xcode-9bee5824e722
Essentially, you do the following:
Setup your table just like you have minus the reusable cell
Create a custom xib file and make it look like your prototype cell (you can simply do this by making an empty object and dragging a tableviewcell onto the storyboard
Make sure to set the class type of the xib to ArtistCell in the Identity Inspector
Create a custom class ArtistCell to hook the xib up to
Use this code when you are setting up your cellForRowAtIndexPath
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell") as? ArtistCell
if cell == nil{
tableView .registerNib(UINib(nibName: "ArtistCell", bundle: nil), forCellReuseIdentifier: "cell")
cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as? ArtistCell
}
cell?.nameLabel.text = "Hello World"
return cell!
}
Here's a screen cap just in case:
This code has been fully tested and works for me. FYI. :-) Hope this helps!
Cheers!
Rob Norback

Custom UITableViewCell from nib in Swift

I'm trying to create a custom table view cell from a nib. I'm referring to this article here. I'm facing two issues.
I created a .xib file with a UITableViewCell object dragged on to it. I created a subclass of UITableViewCell and set it as the cell's 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 complies with no errors but when I run it in the simulator, it looks like this.
In the UITableViewController in the storyboard I haven't done anything to the cell. Blank identifier and no subclass. I tried adding the Cell identifier to the prototype cell and ran it again but I get the same result.
Another error I faced is, when I tried to implement the following method in the 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 article I mentioned I changed the cell parameter's type form UITableViewCell to CustomOneCell which is my subclass of UITableViewCell. But I get the following error,
Overriding method with selector 'tableView:willDisplayCell:forRowAtIndexPath:' has incompatible type '(UITableView!, CustomOneCell!, NSIndexPath!) -> ()'
Anyone have any idea how to resolve these errors? These seemed to work fine in Objective-C.
Thank you.
EDIT: I just noticed if I change the simulator's orientation to landscape and turn it back to portrait, the cells appear! I still couldn't figure out what's going on. I uploaded an Xcode project here demonstrating the problem if you have time for a quick look.
With Swift 5 and iOS 12.2, you should try the following code in order 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 constraints ambiguity message from Xcode:
Here's my approach using Swift 2 and Xcode 7.3. This example will use a single ViewController to load two .xib files -- one for a UITableView and one for the UITableCellView.
For this example you can drop a UITableView right into an empty TableNib.xib file. Inside, set the file's owner to your ViewController class and use an outlet to reference the tableView.
and
Now, in your view controller, you can delegate the tableView as you normally would, like so
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, again, drop a Table View Cell object into an empty TableCellNib.xib file. This time, in the cell .xib file you don't have to specify an "owner" but you do need to specify a Custom Class and an identifier like "TableCellId"
Create your subclass with whatever outlets you need like so
class TableCell: UITableViewCell {
#IBOutlet weak var nameLabel: UILabel!
}
Finally... back in your View Controller, you can load and display the entire thing like so
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 load and display a nib file (the table), and second how to register a nib for cell use.
Hope this helps!!!
Swift 4
Register Nib
override func viewDidLoad() {
super.viewDidLoad()
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
}
Detailed Solution with Screenshots
Create an empty user interface file and name it MyCustomCell.xib.
Add a UITableViewCell as the root of your xib file and any other visual components you want.
Create a cocoa touch class file with class name MyCustomCell as a subclass of UITableViewCell.
Set the custom class and reuse identifier for your custom table view cell.
Open the assistant editor and ctrl+drag to create outlets for your visual components.
Configure a UIViewController to use your custom cell.
class MyViewController: UIViewController {
#IBOutlet weak var myTable: UITableView!
override func viewDidLoad {
super.viewDidLoad()
let nib = UINib(nibName: "MyCustomCell", bundle: nil)
myTable.register(nib, forCellReuseIdentifier: "MyCustomCell")
myTable.dataSource = self
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "MyCustomCell") as? MyCustomCell {
cell.myLabel.text = "Hello world."
return cell
}
...
}
}
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 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
}
}
You did not register your nib as below:
tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCell")
Another method that may work for you (it's how I do it) is registering a class.
Assume you create a custom tableView like the following:
class UICustomTableViewCell: UITableViewCell {...}
You can then register this cell in whatever UITableViewController you will be displaying it in with "registerClass":
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerClass(UICustomTableViewCell.self, forCellReuseIdentifier: "UICustomTableViewCellIdentifier")
}
And you can call it as you would expect in the cell for row method:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UICustomTableViewCellIdentifier", forIndexPath: indexPath) as! UICustomTableViewCell
return cell
}
For fix the "Overriding method... has incompatible type..." error I've changed the function declaration to
override func tableView(tableView: (UITableView!),
cellForRowAtIndexPath indexPath: (NSIndexPath!))
-> UITableViewCell {...}
(was -> UITableViewCell! -- with exclamation mark at the end)
I had to make sure that when creating the outlet to specify that I was hooking to the cell, not the object's owner. When the menu appears to name it you have to select it in the 'object' dropdown menu. Of course you must declare the cell as your class too, not just 'TableViewCellClass'. Otherwise I would keep getting the class not key compliant.
Simple take a xib with class UITableViewCell. Set the UI as per reuirement and assign IBOutlet. Use it in cellForRowAt() of table view like this:
//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
}
100% working without any issue (Tested)
This line add in TableView cell:
static var nib : UINib{
return UINib(nibName: identifier, bundle: nil)
}
static var identifier : String{
return String(describing: self)
}
And register in viewcontroller like
This line use in viewDidLoad
tableview.register(TopDealLikedTableViewCell.nib, forCellReuseIdentifier: TopDealLikedTableViewCell.identifier)
cell for row at indexpath
if let cell = tableView.dequeueReusableCell(withIdentifier:
TopDealLikedTableViewCell.identifier) as? TopDealLikedTableViewCell{
return cell
}
return UITableViewCell()
Set on cell
static var identifier : String {
return String(describing: self)
}
static var nib : UINib {
return UINib(nibName: identifier, bundle: nil)
}

Resources