I get this error when the ViewController loads.
I don't know, what I can do
The loadDataFromDb function is this
func loadDataFromDb() {
let fetchRequest = NSFetchRequest(entityName: "Chats")
daten = self.context!.executeFetchRequest(fetchRequest, error: nil) as! [Model]
tableView.reloadData()
}
I googled that error but nothing helped me
dequeueReusableCellWithIdentifier returns an optional that might be nil.
Your force casting to UITableViewCell, by using as! makes it so that the nil gets casted to UITableViewCell and you end up calling a method on nil, which leads to the exception.
Try unwrapping the cell, by using if let before using it or better yet use dequeueReusableCellWithIdentifier(_ identifier: String,
forIndexPath indexPath: NSIndexPath) -> AnyObject , which doesn't return an optional.
Also as a whole, try staying away from ! and refrain from using it, unless you absolutely have to.
Edit:
Here's one way to do it
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as? UITableViewCell {
cell.textLabel?.text = "Text"
return cell
}
return UITableViewCell()
}
Related
I have seen people writing this code inside a table view delegate
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! SuitCell? else {
fatalError()
}
...
}
now consider this other code
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! SuitCell
...
}
Won't both codes crash at the same lines if the cell is not dequeued?
Is there any difference? I am not seeing it.
dequeueReusableCell(withIdentifier:) can return nil in the case where there are no cells in the re-use pool (i.e. When the tableview is first shown). When it returns nil it is your responsibility to instantiate a cell of the appropriate type.
Therefore, this block of code:
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! SuitCell? else {
fatalError()
}
says "If you get a cell from the re-use pool and it isn't an instance of SuitCell, crash, but nil is OK" (Note the cast to an optional)
While this block of code:
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! SuitCell
Says "Crash if you don't get an instance of SuitCell, or youn get nil", so this will crash when the tableview is first shown.
dequeueReusableCell(withIdentifier:) isn't really used any more. You would use the newer (but still been around since iOS 6) dequeueReusableCell(withIdentifier:,for:) variant as it always returns a cell and you can expect it to be the right class (or you will quickly find your problem during development):
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! SuitCell
I have two core data entities, each with a to-many relationship to the other. I'm using a tableView to allow users to select which wageClasses are related to a given Proposal. The project is Swift 3, iOS 10.2.1, and I'm using the NSManagedObject subClasses from the Editor menu.
This all works great, until I try to add a sixth wageClass to a Proposal. Note: If I try to add any value other than the first 5 into the WageClass array, it crashes. But when I print the array it prints as many values as there are in the array. The app crashes with the error: unexpectedly found nil while unwrapping an Optional value.
I also get a Thread 1: EXC_BREAKPOINT error, but the Breakpoints navigator and lldb list no breakpoints.
I've tested this by trying to add the wageClasses individually, by adding them in different orders, and by creating up to ten wageClasses (to see if it was an issue with the last created wageClass not loading in the tableView) but no luck, I get the same result.
Here's where I'm adding:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "AddWageClassCell", for: indexPath)
let wageClass = wageClasses[indexPath.row]
let wageClassStatus = wageClass.value(forKey: "checked") as? Bool ?? true
cell.textLabel?.text = wageClass.value(forKey: "wageClassName") as? String
var accessoryType = UITableViewCellAccessoryType.none
var tintColor = UIColor.clear
if (wageClassStatus) {
accessoryType = UITableViewCellAccessoryType.checkmark
tintColor = UIColor.green
}
cell.accessoryType=accessoryType
cell.tintColor = tintColor
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let wageClassObject = self.wageClasses[indexPath.row]
var wageClassStatus = wageClassObject.value(forKey: "checked") as? Bool ?? false
wageClassObject.setValue(!wageClassStatus, forKey:"checked")
proposalToEdit?.addToWageClasses(wageClassObject)
do {
try
ad.saveContext()
} catch let error as NSError {
print("Cannot save object: \(error), \(error.localizedDescription)")
}
tableView.deselectRow(at: indexPath,animated:false)
tableView.reloadRows(at: [indexPath], with: .none)
}
Thanks for your comments!
I finally realized that I was force unwrapping a variable when I formatted a cell with wageClasses on a separate tableView on a separate xib. When I wrapped that in an if let statement
if let cell = tableView.cellForRow(at: indexPath) as? WageCell {
configureCell(cell: cell, indexPath: indexPath as NSIndexPath)
} else {
print("something is nil")
}
}
the crash went away.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("nameCell", forIndexPath: indexPath)
let pancakeHouse = pancakeHouses[indexPath.row]
if let cell = cell as? FAQsViewCell {
cell.pancakeHouse = pancakeHouse
} else {
cell.textLabel?.text = pancakeHouse.que
}
return cell
}
I got error in this function of UITableViewController when I run my project at that time I got it I can't understand why it came or what is its meaning.
The "definition conflicts with previous value" occurred also when you forgot to set the Cell Identifier
Make sure you have set the correct identifier to your custom cell (in your case "nameCell") :
I'm trying to use Realm in my UITableViewController and I'm running into issues whenever I try to find the object at a row index if I cast the object to its class (forgive me if I'm using the wrong terminology, I'm still pretty new to Swift, Realm ans iOS dev!)...
I have a Site class which looks like this, and the database has a few thousand entries:
class Site: RLMObject {
var id: String = ""
var name: String = ""
}
In my table view controller, when I try to fetch a Site based on its index in the result set to load into a cell, if I try to cast it to a Site object it's always nil! If I let it be set using AnyObject, then I can see that the correct site at that index has indeed been found.
I'm guessing the .name call on AnyObject is only working because AnyObject responds to .name, but it helps me to see that the index is correct and that the site does exist...
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let allSites = Site.allObjects()
var any: AnyObject = allSites.objectAtIndex(UInt(indexPath.row))
var site = allSites.objectAtIndex(UInt(indexPath.row)) as? Site
println("With AnyObject: \(any.name)")
println("With casting: \(site?.name)")
return cell
}
The result of the print statements above look like this (for example on a site which is named 'Addeboda'):
With AnyObject: Addeboda
With casting: Optional("")
Am I doing something wrong? I've googled around a bit, and all the tutorials and answers I can find along similar lines suggest that results.objectAtIndex(index) as Class should be the right approach.
No cast needed
It seems that casting to Site is not needed. This works fine:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let allSites = Site.allObjects()
let site: AnyObject! = allSites[UInt(indexPath.row)]
cell.textLabel!.text = site.name
println("Site is: \(site.id)")
return cell
}
Seems to be a bug with either Swift or Realm. I'm guessing one of them gets confused when downcasting AnyObject! to something.
Initializing a new instance with correct type
However, if you really need to use the Site model class you can initialize a new RLMObject from the result:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let allSites = Site.allObjects()
let site = Site(object: allSites[UInt(indexPath.row)])
cell.textLabel!.text = site.name
println("Site is: \(site.id)")
return cell
}
First try
It is unfortunate to hear that you are having issues with Realm and Swift. I am by no means a Swift pro, but it looks like you are casting site to an optional, and the result of using the optional cast operator site?.name is also an optional. Hence getting Optional("").
Can you try to see if you have any better luck with the following?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let allSites = Site.allObjects()
if var site = allSites[UInt(indexPath.row)] as? Site {
println("Site is: \(site.name)")
} else {
println("it not castable to Site. It is: \(toString(allSites[UInt(indexPath.row)].dynamicType))")
}
return cell
}
Also, you can use yourObject.dynamicType to get a reference to the objects real class type.
Best of luck
Here is some code from the tableview sample project:
class TableViewController: UITableViewController {
var array = DemoObject.allObjects().sortedResultsUsingProperty("date", ascending: true)
...
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as Cell
let object = array[UInt(indexPath.row)] as DemoObject
cell.textLabel?.text = object.title
cell.detailTextLabel?.text = object.date.description
return cell
}
}
You should be able to cast on the line you are storing that indexPath.row object
I have a tableview in my app and when I start my app it crashes on the following function.
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
// Configure the cell...
let cellId: NSString = "Cell"
var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellId) as UITableViewCell
}
It crashes on the line of var cell
It gives the following error:
I can't figure out what's wrong with my code.
The whole function:
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
// Configure the cell...
let cellId: NSString = "Cell"
var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellId) as UITableViewCell
let data: NSManagedObject = mylist[ip.row] as NSManagedObject
cell.textLabel.text = data.valueForKeyPath("voornaam") as String
cell.detailTextLabel.text = data.valueForKeyPath("achternaam") as String
return cell
}
EDIT:
What I got now:(Still gives the same error)
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell? {
// Configure the cell...
let cellId: NSString = "Cell"
var cell: UITableViewCell? = tableView?.dequeueReusableCellWithIdentifier(cellId) as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style: .Subtitle, reuseIdentifier: cellId)
}
let data: NSManagedObject = mylist[indexPath.row] as NSManagedObject
cell!.textLabel.text = data.valueForKey("voornaam") as String
cell!.detailTextLabel.text = data.valueForKey("achternaam") as String
//cell!.textLabel.text = "Hoi"
return cell
}
This is happening because the as operator is defined to cast an object to a given type and crash if the conversion fails. In this case, the call to dequeue returns nil the first time you call it. You need to use the as? operator, which will attempt to cast the given object to a type, and return an optional that has a value only if the conversion succeeded:
var cell: UITableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellId) as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style: .Subtitle, reuseIdentifier: cellId)
}
...
Because cell is now an optional value, use cell! when you want to call methods on it to force-unwrap the UITableViewCell inside it.
Additionally, your code had a second problem: it never created a fresh cell. dequeue will return nil the first time it's called on your table view. You need to instantiate a new UITableViewCell as in my code sample and then return it from the cellFor... method. The table view will then save the cell and return it on future calls to dequeue.
First off, why are you doing an optional binding on line if let ip = indexPath? This argument is not optional and you don't need to do optional binding or unwrap it. But this shouldn't cause your code to crash.
Remove your let data line and assign literal strings to your cells and see if it still crashes.
May I suggest that you check to see if you set the tableview's delegates? I made that mistake once in the flurry of setting everything else up.
Perhaps it is too late but I like to share my experience. I had similar error as I copied the entire code from another project. So I think the variables and functions won't be recognised so I had to drag them (cntr+drag) then it is solved.
Sorry if I couldn't explain better. I am new this.