i'm making an app that needs to transfer data using segues and cells. I have two nearly identical View Controllers but one of them is getting the following error on line 3 whenever I launch it:
I know that Bad Instruction errors mean that it is finding nil, but I don't know how to fix it. This is the code that isn't working:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: InstrumentTableCell! = tableView.dequeueReusableCellWithIdentifier(identifier) as? InstrumentTableCell
cell.configurateTheCell(recipies[indexPath.row])
return cell!
}
How do I fix this?
Related
when i implement either proposed fix the app crashes when run. When i compile/run the app without the recommended fix the app runs as expected.
the original method is as follows:
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell {
//this let statement is my original line of code prior to swift 3 conversion and it worked fine
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier:"Cell")
//i've tried using the statement below instead but still getting same error
//let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = userSummaryArray[(indexPath as NSIndexPath).row] as String
cell.textLabel!.font = UIFont(name:"Helvetica Neue", size:17)
cell.accessoryType = .disclosureIndicator
userSummaryTable.rowHeight = 25
return cell
}
after converting to swift 3 in Xcode8 i'm now getting a warning on this method that reads:
Instance method 'tableView(_:cellForIndexPath:)' nearly matches optional requirement 'tableView(_:heightForRowAt:)' of protocol 'UITableViewDelegate'
There are two options recommended to "fix" the warning:
Make 'tableView(_:cellForIndexPath:)' private to silence this warning
OR
Add '#nonobjc' to silence this warning
Both of these "fixes" crash the app. the original code works fine in the new swift and worked fine in the older version of swift. what are these recommendations?
Any help is very much appreciated.
Make that
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
instead of
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell {
Xcode is trying to help you but does not recognize that
I had the same issue. Along with Lu_s answer, make sure you add UITableViewDataSource to the class.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { }
I already know the solution for my problem, but I just really don't understand what's going on here. I have a UITableViewController that takes the cell in didSelectRow and uses it for something in an other function. I pass the cell as AnyObject?. Now when I drill down into a detail VC and then back up again, repeat those steps 2 more times, my app crashes.
First I thought it's a problem somewhere else in my app, but then I created a sample project with nothing but those few lines and managed to reproduce the bug. I also already filed a radar, but I don't want to die dump (as you never hear back form those radar guys) ;) Can anybody explain to me what's going on here!
final class MasterViewController: UITableViewController {
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let cell = tableView.cellForRow(at: indexPath)
doSomethingWith(sender: cell)
}
}
extension MasterViewController {
func doSomethingWith(sender: AnyObject?) {
// I don't even use that sender!!!
// If the function would read doSomethingWith(sender: Any?) everything would be ok!
}
}
If you want you could download the whole sample at: http://www.georgbachmann.com/demo/CrashTest.zip
I'd really like to know what the swift compiler is doing there!
::EDIT::
I just noted that the crash also depends on doSomethingWith: being in an extension!
Basically, you don't "own" the reusable cells. The UITableView owns them. Since you're passing the same cell three times to the function with strong reference (you wrote, you know the solution, so I'm omitting it), you increase the ref count of the cell (in this case to be +3, but it doesn't matter). At some point the UITableView decides to release its cells, but your UIViewController has a strong reference to them. At this point the app crashes. No bug here - you should never pass objects that you don't own.
I'm moving and app I had on Parse to Firebase and I ran into an issue with a cell that needs to get resized.It contains a textview that recieves data, since the text varies in size, I am using this two methods:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
With Parse this worked perfectly because I would recieve the entire object that I had to pass to the DetailTableView in the MainTableView. With Firebase, I handle it differently, I retrieve what the MainTableView needs, then I just pass a reference to the DetailTableView and again retrieve whatever I need there. The problem seems to be that the size of the cell gets set before the async function can set the text. Any ideas on how to solve this?
Thanks in advance!
I think you can wrap the code setting the text on the cell with calls to tableView.beginUpdates()
tableView.endUpdates()
Using UITableView with one Prototype cell inside a ContainerView. The table will need to provide cells so that at run time, the code will add different views in different cells for user information and interaction.
The connection is made between the tableView and the containerView.swift to be its dataSource and delegate.
In the containerView.swift, the UIViewController has been extended.
extension myContainerView: UITableViewDataSource, UITableViewDelegate {...}
And in that block of code, there are required func which return numberOfRowsInSection and cellForRowAtIndexPath
But these infos are available at run time and thus my code is not complying now, I get this following error when return parent.mainTbRowCount() is reached, and if I return just a dummy int for now, I get the same error when let view = parent.cellsViewsDesider.views![indexPath.row] is reached.
fatal error: unexpectedly found nil while unwrapping an Optional value
extension myContainer: UITableViewDataSource, UITableViewDelegate {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return parent.mainTbRowCount() // <------ fatal error
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("topCellId", forIndexPath: indexPath)
let view = parent.cellsViewsDesider.views![indexPath.row] // <---- fatal error
cell.contentView.addSubview(view!)
return cell
}
If I delete the connection which I made between the tableView and the containerView.swift to be its dataSource and delegate, the code compiles but the functions for numberOfRowsInSection and cellForRowAtIndexPath never get called.
What needs to be done in this case?
Thank you
I'm building a table that has two cells of the same class but of different identifiers.
I am using a segmented control to display either or.
I believe everything is hooked up properly on Storyboard, however,
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let friendRequest = self.friendRequestsToDisplay[indexPath.row]
requestDirection = isAnIncomingRequest ? "IncomingRequestCell" : "OutgoingRequestCell"
if let cell = tableView.dequeueReusableCellWithIdentifier(requestDirection) as? RequestCell {
cell.configureCell(friendRequest, isAnIncomingRequest: isAnIncomingRequest)
return cell
} else {
return UITableViewCell()
}
}
FAILS AT dequeueReusableCellWithIdentifier, according to breakpoints, with:
fatal error: unexpectedly found nil while unwrapping an Optional value
After hard coding the Identifiers ("IncomingRequestCell" and "OutgoingRequestCell" in the dequeueReusable... method as suggested in the comments, it appears that these values are the source of the problem. However, they properly identify their respective UITableViewCells in IB.
Any ideas?
Why you use global variable for reuseIdentifier and update it every time? You can use local var for it.
Also avoid using dequeueReusableCellWithIdentifier, please use dequeueReusableCellWithIdentifier:forIndexPath: instead. I had some strange issues in one of my previous project because of it.
Here is quick example, which works like a charm:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let identifier = (indexPath.row == 0) ? "Cell1" : "Cell2"
let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath)
self.configureCell(cell, atIndexPath: indexPath)
return cell
}
UPDATE: After investigation, we figured, that problem was in custom cell class initialization code.
If everything is hooked up properly - which means that you correctly set your reuseIdentifiersin IB and the UITableViewCells are prototyp cells within your UITableView (and not loaded from a nib - which requires manually registering the UITableViewCells), than just use
dequeueReusableCellWithIdentifier:forIndexPath: