This code was from a now inactive tutorial that helped me load in data to a table view. Since the tutorial was written in Swift 2.0, I believe that this was changed in Swift 3. I know that the override function itself was changed, which I handled. But now, it brings me a Thread 1: EXC_BAD_INSTRUCTION(code=EXC_1386_INVOP, subcode=0x0)
error.
Update: I have tried multiple things including creating a custom class for the cell. I still either get the same error I listed above, or a Thread 1: Signal SIGABRT
error on the first line of my App Delegate file. Creating a breakpoint hasn't helped me because I know where the error is coming from.
import UIKit
import Firebase
import FirebaseDatabase
struct postStruct {
let title : String!
let message : String!
}
class LoggedInController: UITableViewController {
var posts = [postStruct]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("Posts").queryOrderedByKey().observe(.childAdded, with: {
snapshot in
let snapshotValue = snapshot.value as? NSDictionary
let title = snapshotValue!["title"] as? String
let message = snapshotValue!["message"] as? String
self.posts.insert(postStruct(title: title, message: message), at: 0)
self.tableView.reloadData()
})
post()
}
func post(){
let title = "Title"
let message = "Message"
let post : [String : AnyObject] = ["title" : title as AnyObject,
"message": message as AnyObject]
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("Posts").childByAutoId().setValue(post)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell")
let label1 = cell?.viewWithTag(1) as! UILabel
label1.text = posts[indexPath.row].message
let label2 = cell?.viewWithTag(2) as! UILabel
label2.text = posts[indexPath.row].message
return cell!
}
}
Update 2: Here is the new code I used. It's not pretty and only gets the title.
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
cell?.textLabel?.text = posts[indexPath.row].title
cell?.detailTextLabel?.text = posts[indexPath.row].message
return cell!
} else {
let label1 = cell?.viewWithTag(1) as? UILabel
label1?.text = posts[indexPath.row].title
let label2 = cell?.viewWithTag(2) as? UILabel
label2?.text = posts[indexPath.row].message
return cell!
}
}
Ok this code
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
produces an optional calledcell
that may or may not contain a a valid instance of UITableViewCell. Optionals in Swift are a way to safeguard against nil values, you can read more about optionals here: OptionalsOn the first run when your table view wants to load its data it calls all the required methods of your
UITableViewDataSource
. The first run is a critical one because there aren't any instances of the UITableViewCell the table view can dequeue yet. To solve your problem you have to do something similar to the code below:Code similar to the one above are usually used to programmatically add an instance of
UITableViewCell
. However, if you used interface builder to add a prototype cell use thelet cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
method to dequeue your cells in which case it does not return an optional and you do not need to do all the if / else blocks. Something else I wanted to mention about your code is finding sub views buy their ID will not produce a very object oriented code and that maybe the source of your errors where the compiler can not find the sub views. The better way would be to use one of the built in instances of UITableViewCell such as.default
or alliteratively you could subclass the said class and make your very own custom cells.Hope this helped!
Try this
Edited
Make Sure you did these things
UITableViewController
In
viewDidLoad()
In
cellForRowAt indexPath
UITableviewCell.XIB Hope u did these things
![Outlet](https://i.stack.imgur.com/LjYU2.png)
UITableviewCell
Make sure the dot appears so that the
@IBOutlet
is connected with the xib labelUsing
dequeueReusableCell
, you are accessing cell which doesn't exists. To make your code work change the below line:To