Firebase Database - Fatal error: Unexpectedly found nil while unwrapping an Optional value - swift

I'm trying to populate a label in my custom cell for my UITableViewController with information from my Firebase Database but I keep running into this error:
"Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value"
I did read this link: What does "fatal error: unexpectedly found nil while unwrapping an Optional value" mean?
I don't think I'm accessing outlets before they're loaded in and I did check that my IBOutlet connection is correct.
class FeedCell: UITableViewCell {
#IBOutlet weak var postText: UILabel!
}
class FeedTableViewController: UITableViewController {
var postInfo = FeedCell()
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
self.tableView.rowHeight = 100.0
// postText = UILabel()
//
var ref: DatabaseReference!
ref = Database.database().reference()
let cellRef = ref.child("post/body")
cellRef.observeSingleEvent(of: .value) { (snapshot) in
if let body = snapshot.value as? String {
self.postInfo.postText.text = body
print(body)
}
}
}
I expected the label to be updated with the body text "test firebase" but I'm just running into that error. Is it because I defined my IBOutlet in another class then referenced it in my FeedTableVIewController? Any advice would be appreciated!

The problem is here
var postInfo = FeedCell()
with
self.postInfo.postText.text = body <<< postText is nil
First you shouldn't create an instance var of a cell , and as your current var here postInfo is initated with FeedCell() so the outlet is nil regardless of it's connected / not
Second you should make use of table delegate and dataSource methods to populate your table

Related

Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value [duplicate]

This question already has answers here:
What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean?
(16 answers)
Closed 2 years ago.
My Swift program is crashing with a fatal error, saying that "Unexpectedly found nil while implicitly unwrapping an Optional value" even with the GUARD statement . Can anyone help to tell me why, and how do I fix it? The code as follows:
var page: Page? {
didSet{
guard let unwrappedPage = page else { return }
NameLabel.text = unwrappedPage.dishName
Image.image = UIImage(named: unwrappedPage.imageName)
contentText.text = unwrappedPage.ingredient
contentText.text = unwrappedPage.instruction
}
}
The issue is likely that the outlets have not been hooked up by the time you set page, and if these outlets are implicitly unwrapped optionals (with the ! after the type name, e.g. UILabel!), that will result in the error you describe. This problem will manifest itself if, for example, you set page before the view controller in question has been presented and all of the outlets have been hooked up.
So, I’d recommend:
Use optional chaining with your #IBOutlet references so it won’t fail if the outlets haven’t been hooked up yet.
Go ahead and keep your didSet observer on page, if you want, but make sure you also update the controls in viewDidLoad in case page was set before the outlets were hooked up.
For example:
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var imageView: UILabel!
#IBOutlet weak var ingredientLabel: UILabel!
#IBOutlet weak var instructionLabel: UILabel!
var page: Page? { didSet { updateControls(for: page) } }
override func viewDidLoad() {
super.viewDidLoad()
updateControls(for: page)
}
func updateControls(for page: Page?) {
nameLabel?.text = page?.dishName
imageView?.image = page.flatMap { UIImage(named: $0) }
ingredientLabel?.text = page?.ingredient
instructionLabel?.text = page?.instruction
}
Note, you only need this didSet observer if the page might be set (again) after the view has been presented. If not, the didSet observer is not needed.

Assigning text field value to variable in Swift

I am trying to learn Swift and it is turning out to be more different from other languages than I expected...
I just want to store the value of a user's input as an integer in a variable.
My attempts result in the following error:
"fatal error: unexpectedly found nil while unwrapping an Optional value"
I have tried this multiple ways and can't seem to come up with a solution, I know there must a simple way to do this.
var intNumber: Int = 0
#IBOutlet weak var txt_Number: UITextField!
for view in self.view.subviews as [UIView]{
if let txt = view as? UITextField
{
if let txtData = txt.text where txtData.isEmpty
{
// Error Message
}
else
{
intNumber = Int(txt_Number.text)
}
}
}
I know the above code isn't correct, but I think that's the closest to correct I have come. I seem to be missing something as far as unwrapping goes. I understand the principal of unwrapping, but nothing I have tried will compile, or if it does compile then it fails with the error above when the code is initiated (code is initiated when a button is pressed).
Thank you in advanced for any help!
A couple of thoughts:
Make sure your outlet is hooked up to txt_Number. All of that code checking to make sure it's not nil is not necessary if (a) it's an outlet you hooked up in IB; and (b) you're not doing the above code before the view is completely loaded (i.e. viewDidLoad was called).
If the outlet is not hooked up, you'll see an empty dot on the left margin:
If it is hooked up correctly, you'll see a filled in dot on the left margin:
If everything is hooked up correctly, you can just do:
guard let txtData = txt_Number.text, let value = Int(txtData) else {
// report error and then `return`
return
}
intNumber = value
If you want to get fancy, you might want to ensure the user only enters numeric values by
In viewDidLoad, specify that the keyboard is for decimal numbers only.
txt_Number.keyboardType = .NumberPad
Or you can specify this in IB, too.
Specify a delegate for the text field and only allow them to enter numeric values. (This might seem redundant based upon the prior point, but it's not, because you have to also anticipate them pasting in a string to the text field.)
See https://stackoverflow.com/a/26940387/1271826.
For starters, you don't have to iterate over subviews if you have direct reference txt_Number, but this is not an essence of your question.
if let semantics will let you unwrap any optional inside {} brackets, so the most visible solution here is to:
if let unwrappedString = txt_Number.text {
if let unwrappedIntegerInit = Int(unwrappedString) {
intNumber = unwrappedIntegerInit
}
}
My full example from playgrounds:
var intNumber: Int = 0
var txt_Number: UITextField = UITextField()
txt_Number.text = "12"
if let unwrappedString = txt_Number.text {
if let unwrappedIntegerInit = Int(unwrappedString) {
intNumber = unwrappedIntegerInit
}
}
print(intNumber)
Or you can use guard inside a function:
func parse() {
guard let text = txt_Number.text, let number = Int(text) else { return } // no text
intNumber = number
}
TIP:
You have to unwrap txt_Number.text and Int(text) separately cause Int(text) has to have nonoptional argument.
Did you try with this?
if let txtData = txt.text where !txtData.isEmpty
{
intNumber = Int(txtData)
}
else
{
// Error Message
}
ADD:
Int() function returns an Optional. If you are sure that the value is correct, you can force the unwrapping by using ! at the end of the variable name (when you are using it), otherwise just put the question mark ?
tried below code to assign value of TextField to variable of float type and all bug disappear like magic
#IBOutlet weak var txtamount: UITextField!
#IBOutlet weak var txtrate: UITextField!
#IBOutlet weak var txtyear: UITextField!
#IBOutlet weak var lblresult: UILabel!
#IBAction func btncalculate(_ sender: UIButton)
{
print("button is clicked")
var amount,rate,year,answer : Float
amount = Float(txtamount.text!)!
rate = Float(txtrate.text!)!
year = Float(txtyear.text!)!
answer = (amount * rate * year) / 100.0
}

I'm getting nil error with image?

i'm getting fatal error: unexpectedly found nil while unwrapping an Optional value
imagedata is not nil it has a value of 2604750 bytes
I don't know why it show this error as I can see img1 is nil why ?
any comments !!!
#IBOutlet var img1: UIImageView!
#IBOutlet var img2: UIImageView!
// in viewWillAppear I gave it a default image
self.img1.image = UIImage(named: "dummy.png" )
self.img1.image = UIImage(named: "dummy.png" )
// i changed to send the nsmanagedobject but it's still same error
func setimage(person: NSManagedObject){
let data: NSData = NSData()
if person.valueForKey("picture") as! NSData == data{
if person.valueForKey("tag") as! Int == 1 {
img1.image = UIImage(named: "dummy" )
}else if person.valueForKey("tag") as! Int == 2 {
img2.image = UIImage(named: "dummy")
}}
else{
if person.valueForKey("tag") as! Int == 1 {
img1!.image = UIImage(data: person.valueForKey("picture") as! NSData )
}else if person.valueForKey("tag") as! Int == 2 {
img2.image = UIImage(data: person.valueForKey("picture") as! NSData )
}
}
}
So, you have a simple mistake. In fact your outlets were nil. However, not because you did not assign them in the storyboard, but because the setimage was called on a different instance of ViewController.
You have a property view1 in your second view controller which is declared as:
let view1: ViewController = ViewController()
This creates a NEW instance of ViewController. When you then call view1.setimage you get a crash because outlets for THIS instance are not connected.
The property in your second view controller should be
var view1: ViewController!
and in your imageTapped method of the ViewController you should modify code so it has this line:
view.view1 = self
Forced unwrapping might not be ideal, but it should work as long as you ensure that whenever you instantiate your second view controller you set the view1 property.
I think is the same thing as Andriy is suggesting. Probably your Outlet for the image is not connected with the view.
Your outlets are nil, there are a couple of reasons why this could happen.
They have not been connected in the interface builder.
You are accessing them before they have been instantiated, e.g. before viewDidLoad() has been called.

Swift Promises - Reload Data method is not binding the data

I'm using promises to retrieve information some methods via JSON. I'm filling the information with the function:
I'm trying to set those records in my TableView with:
#IBOutlet weak var usersTableView: UITableView!
var dataSource: [UserResponse]? {
didSet {
self.usersTableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
loadFriends()
// Do any additional setup after loading the view.
}
func loadFriends() {
//UserService.getFriends()
let (request, promise) = UserService.getFriends()
promise.then { user in
self.dataSource = user
}.catch{
error in
SCLAlertView().showError("Error", subTitle: error.localizedDescription)
}
}
But is returning the error:
fatal error: unexpectedly found nil while unwrapping an Optional value
How I can fix this error?
Your usersTableView is an implicitly unwrapped optional (UITableView!). When you call the dataSource setter, the didSet property observer tries to call reloadData() on usersTableView, but it is nil, so you get a crash - you cannot call methods on nil.
It looks like you haven't connected the outlet to your usersTableView property in your storyboard. Alternatively, you're setting it to nil somewhere else in your code. This could be happening automatically if usersTableView isn't part of your view hierarchy when the view controller is loaded, since it is a weak variable, but I expect you have added it as a subview in the storyboard?

Why am I getting a nil for a UITableViewCell's UILabel?

Why am I getting a 'nil' error/UILabel during my second pass thru the table cell listing iteration?
1) Inside cell
2) Inside cell
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb) po cell?.contentView.viewWithTag(TitleLabelTag)
nil
Here I link the elements in the code; and register the cell:
class DiaryTableViewCell: UITableViewCell {
#IBOutlet weak var TitleLabel: UILabel!
#IBOutlet weak var SubTitleLabel: UILabel!
#IBOutlet weak var leftImageView: UIImageView!
#IBOutlet weak var rightImageView: UIImageView!
}
class DiaryTableViewController: UITableViewController {
let kCellIdentifier = "DiaryCell"
var cellNib:UINib?
var diaryCell:DiaryTableViewCell?
var objects = NSMutableArray() //...global var.
override func viewDidLoad() {
self.title = "My Diary"
cellNib = UINib(nibName: "TableViewCells", bundle: nil)
tableView.registerClass(DiaryTableViewCell.self, forCellReuseIdentifier: kCellIdentifier)
}
...
Yet I'm getting the runtime error here:
Here's what I get in the console:
1) Inside cell
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb) po cell!.TitleLabel
nil
What's missing here?
It's a pretty bad idea to select a view with a tag. It's a much better idea to subclass your UITableViewCell and give it a property to access the elements.
If you are creating static cells and loading you need to create an IBoutlet for them in your .h correctly.
Moreover remove line
tableView.registerClass(...) statement from your code. Look at this link might help and is very similar except its for collectionview. -
Why is UICollectionViewCell's outlet nil?
1) I moved the cell registration to the viewDidLoad().
2) I forgot to place the '?' after the TitleLabel & SubTitleLabel; to notify the compiler that these labels could be nil.
I don't see the altered cell yet (empty rows); but I'm not getting runtime errors.
Unfortunately I merely cured the symptom; not the cause. I'm still getting nil UILabels.
...working on revision and cleaner code.