Load UITableViewCell from xib file in a UITableView in a view - ios

I have a view (not a view controller) that pop up when I press a button.
In this view, I have a UIButton and a UITableView. I want to use the UITableViewCell I designed in a xib file.
So I created my cell class:
class PickerViewCell: UITableViewCell {
#IBOutlet weak var flagImageView: UIImageView!
#IBOutlet weak var codeLabel: UILabel!
#IBOutlet weak var nameLabel: UILabel!
func setCell(myObject: myObject) {
flagImageView.image = UIImage(named: myObject.code)
codeLabel.text = myObject.code
codeLabel.font = myObject.kPickerViewCodeFont
nameLabel.text = myObject.name
nameLabel.font = myObject.kPickerViewNameFont
}
}
My xib file:
Here I didn't set the owner of the xib (I tried with as well), I put the custom class for the UITableViewCell and no reuse identifier (I tried with as well).
In the init function of my view (the one containing the table view), I do the following:
let nib = UINib(nibName: "PickerViewCell", bundle: nil)
tableView.registerNib(nib, forCellReuseIdentifier: "cell")
And finally I implement the method:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! PickerViewCell
let myObject = myObjects[indexPath.row]
cell.setCell(myObject)
return cell
}
When I want to show (create) my view, the debugger stop at
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! PickerViewCell
and I get the following error:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSObject 0x7f9b934d8c70> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key codeLabel.'
What's wrong?
EDIT:

Check your connection of #IBOutlet weak var codeLabel: UILabel! with IB in PickerViewCell. Try to reconnect it.

Related

How to proper create a custom cell with a xib file, register, and load it ?

I want
to create a custom table cell and add all the components and register it
I did
I created these files below :
PlaceDetailCell.xib
with the id of customPlaceDetailCell
CustomPlaceDetailCell.swift
import UIKit
class CustomPlaceDetailCell: UITableViewCell {
#IBOutlet weak var country: UILabel!
#IBOutlet weak var address: UILabel!
#IBOutlet weak var distance: 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
}
}
I register
//register xib file
placesTable.register(UINib(nibName: "PlaceDetailCell", bundle: nil), forCellReuseIdentifier: "customPlaceDetailCell")
This is my cellForRowAt
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customPlaceDetailCell", for: indexPath)
as! CustomPlaceDetailCell
if places[indexPath.row]["name"] != nil {
cell.textLabel?.text = places[indexPath.row]["name"]! + " (" + distances[indexPath.row] + " miles)"
}
return cell
}
I got
a crash when I click on that cell even if the app is successfully Build.
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key address.'
*** First throw call stack:
I hope
someone can provide some guidance for me to do the right things.
You need to set the xib file custom class to the class you cast it to
let cell = tableView.dequeueReusableCell(withIdentifier: "customPlaceDetailCell", for: indexPath)
as! CustomPlaceDetailCell
as it seems that xib name is PlaceDetailCell with class PlaceDetailCell and you cast it to CustomPlaceDetailCell
if you register this
placesTable.register(UINib(nibName: "PlaceDetailCell", bundle: nil), forCellReuseIdentifier: "customPlaceDetailCell")
then the xib custom class should be set to CustomPlaceDetailCell not to PlaceDetailCell which is expected as always the xib name = it's class name that you create and then wanted to change the class name

unable to dequeue a cell with identifier cell with properly defined identifier

I experienced weird issue with TableViewController
*** Assertion failure in -[UITableView _dequeueReusableCellWithIdentifier:forIndexPath:usingPresentationValues:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3694.4.18/UITableView.m:7732
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
It makes no sense while
Identifier is set properly.
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
However if i place
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
in ViewDidLoad, then it works. However prototype from storyboard will not and is not used.
At this point i have no idea what's going on.
TableViewController class is set also correctly.
I understood your question, There are only one reason that your tableview can not find the registered cell.
Solution is that you have to check your code one more time. Please check your identifier spelling in both storyboard and cellForRowAt method.
if this solution not work than follow this steps:
paste below code in cellForRowAt method
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
return cell
Delete all cells from tableviewcontroller from storyboard.
Drag and drop new TableViewCell and give proper indetifer "cell"
Build and run.
This solution will definitely work.
As you using a TableViewCell Differently So I am sure you had also created a tableCell Class , as in my case its "CustomTableCellClass" as follow
class CustomTableCellClass: UITableViewCell {
weak var CategoriesDelegate: CategoriesVcDelegate?
weak var itemsDelegate: ItemsvcDelegate?
//MARK: Outlets of CategoriesVcTableView
#IBOutlet weak var ProductImage: UIImageView!
#IBOutlet weak var ProductName: UILabel!
#IBOutlet weak var ProductPrice: UILabel!
#IBOutlet weak var ProductStarImage: UIButton!
}
My cellReuseIdentifier Declaration -
let cellReuseIdentifier = "cell"
Now Deque it as
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.CategoriesTableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! CustomTableCellClass
cell.CategoriesDelegate = self
cell.ProductStarImage.tag = indexPath.row
cell.ProductName.text = productNameArray[indexPath.row]
cell.ProductPrice.text = productPriceArray[indexPath.row]
cell.ProductImage.image = productImagesArray[indexPath.row]
return cell
}
Hope it helps :)
It seems that issue was in custom library i was using for navigation. Instead initialising view controller from storyboard identifier, it was initialising class directly, thus storyboard view controller was useless.
Everything works well now.

this class is not key value coding-compliant for the key

I am very new to swift development and I am working on this section of an apple provided swift tutorial. I created an outlet for a label, image, and custom view that are nested in a Table Cell. When I run I get this error
2016-07-20 23:16:11.110 FoodTracker[8446:3016336] Unknown class MealTableViewCell in Interface Builder file.
2016-07-20 23:16:11.124 FoodTracker[8446:3016336] * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key nameLabel.'
* First throw call stack:
There are no duplicate outlets and I believe the cellIdentifier used in my Table View Controller is correct.
My table cell
import UIKit
class MealTableViewCell: UITableViewCell {
// MARK: Properties
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var photoImageView: UIImageView!
#IBOutlet weak var ratingControl: RatingControl!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}}
My Table View Controller
import UIKit
class MealTableViewController: UITableViewController {
// MARK: Properties
var meals = [Meal]()
override func viewDidLoad() {
super.viewDidLoad()
loadSampleMeals()
}
func loadSampleMeals() {
let photo1 = UIImage(named: "meal1")!
let meal1 = Meal(name: "Caprese Salad", photo: photo1, rating: 4)!
let photo2 = UIImage(named: "meal2")!
let meal2 = Meal(name: "Chicken and Potatoes", photo: photo2, rating: 5)!
let photo3 = UIImage(named: "meal3")!
let meal3 = Meal(name: "Pasta with Meatballs", photo: photo3, rating: 3)!
meals += [meal1, meal2, meal3]
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return meals.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "MealTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! MealTableViewCell
// Fetches the appropriate meal for the data source layout.
let meal = meals[indexPath.row]
cell.nameLabel.text = meal.name
cell.photoImageView.image = meal.photo
cell.ratingControl.rating = meal.rating
return cell
}}
Thanks!
Check for a broken outlet link in your storyboard file. Find your controller and control-click on the yellow circle above its nib to open the actions and outlets popover. You should see an outlet for nameLabel with a yellow warning sign. Either reconnect it to your controller's file or remove it if its a duplicate.
Its very simple , the story board can not find the outlet with the name "nameLabel". So either create a label by that name or delete the reference of the created label from the storyboard.
Here are the steps
Just click the storyboard and select the last Tab.
Now search for the nameLabel and click on cross to disconnect.
All the best ;)
First, you must link your UITableView from your interface builder to your MealTableViewController class ( Ctrl + drag )
Then, in the viewDidLoad method of your MealTableViewController class, you must register your custom cell class to your table view :
self.tableView.registerClass(MealTableViewCell.self, forCellReuseIdentifier: "MealTableViewCell")

This class is not key value coding-compliant for the key...why?

I've linked output from the IB to the code, as shown below.
class DiaryTableViewCell: UITableViewCell {
#IBOutlet weak var TitleLabel: UILabel!
#IBOutlet weak var SubTitleLabel: UILabel!
#IBOutlet weak var leftImageView: UIImageView!
#IBOutlet weak var rightImageView: UIImageView!
}
Here, I'm registering the class:
override func viewDidLoad() {
self.title = "My Diary"
cellNib = UINib(nibName: "TableViewCells", bundle: nil)
tableView.registerClass(DiaryTableViewCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)
}
But I keep getting the following runtime error:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '...setValue:forUndefinedKey:]: this class is not key value
coding-compliant for the key SubTitleLabel.'
From within the following code:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as DiaryTableViewCell?
if (cell == nil) {
tableView.registerClass(DiaryTableViewCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)
cell = cellNib?.instantiateWithOwner(self, options: nil)[0] as? DiaryTableViewCell
cell?.selectionStyle = .None
}
if (cell != nil) {
println("\(x++)) Inside cell")
cell!.TitleLabel.text = "Hello"
cell!.SubTitleLabel.text = "World"
}
return cell!
}
Specifically, it's happening here:
cell = cellNib?.instantiateWithOwner(self, options: nil)[0] as? DiaryTableViewCell
Question: How am I violating the key value coding-compliant for a UILabel?
This hasn't happened before... UILabel is KVO compliant.
I linked to the WRONG Source!
Here's the result:
You should not be calling instantiateWithOwner yourself inside tableView:cellForRowAtIndexPath.
Register the nib in viewDidLoad and then dequeueReusableCellWithIdentifier will do all the work for you.
The reason for your particular error is that you are calling instantiateWithOwner passing self as the owner and so the nib is trying to wire the outlets up to your UITableViewDataSource implementation class rather than a DiaryTableViewCell.
Show the references of your ViewController rigth-clicking in it on the Document Outline. Probably you will see a warning in one of the references. Delete it and link it again if still need it.
sometimes its like when you create button in your xib, you create one button and copy paste other buttons from one buttons, in that case this error occurs, and yes removed connections from xib could also be an reason.
I have created a TableViewCell same like your & have the same problem. I have research solving the problem but nothing. Then I delete Label in TableViewCell and recreate again, connect it to TableViewCell through File Owner,v..v And the result is right. No error. You should recreate them again.

Swift iOS custom cell properties can't be changed (unwrap empty optional)

I have gone through all the questions regarding this matter that seems to be popular. Anyhow, I have created a simple app with a table view that uses custom cells.
I use the storyBoard, and defined the cells with the same name the class I created, Xcode even auto-completed me.
Though when I initialise a new cell, I can't change the properties of the labels and image contained in the cell. I receive an error saying I accessed a nil, and I kinda get it. Though I couldn't seem to find a way around it. Can someone help?
import UIKit
class ExtenderCell: UITableViewCell {
#IBOutlet var main_image: UIImageView!
#IBOutlet var name_label: UILabel!
#IBOutlet var desc_label: UILabel!
init(to_put_image: UIImage, name: String, desc:String){
super.init(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
name_label.text = name
desc_label.text = desc
main_image.image = to_put_image
}
}
You are using storyBoard for cell creation with outlets.Your outlets are not accessible to you till awakeForNib() using storyBoard as it is not unarchived till awakeFromNib. Your outlets or properties are nil in init so you are getting this exception as you are trying to unwrap nil outlet property in init method.
As your outlet properties are not accessible in init method and they are nil in init.So you need to set your outlets in awakeForNib().Or you can set the properties in cellForRowAtIndexPath.So best approach is to make your init method as instance method if you want to use storyBoard.
import UIKit
class ExtenderCell: UITableViewCell {
#IBOutlet var main_image: UIImageView!
#IBOutlet var name_label: UILabel!
#IBOutlet var desc_label: UILabel!
func setContents(to_put_image: UIImage, name: String, desc:String){
name_label.text = name
desc_label.text = desc
main_image.image = to_put_image
}
}
set the contents of cell in cellForRowAtIndexPath
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//Check your identifier in storyBoard is "cell"
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as ExtendedCell
cell.setContents(yourImage, name: yourName, desc: yourDescription)
return cell
}

Resources