fatal error: unexpectedly found nil while unwrapping an Optional value [duplicate] - ios

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.
I am trying to run this code but I keep on getting this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
I don't understand what it means or why I'm getting it. Any hint?
import UIKit
class ViewController: UIViewController {
var lastNumber: String = ""
#IBOutlet var answerField: UILabel
#IBOutlet var operaterLabel: UILabel
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func buttonTapped(theButton: UIButton) {
if answerField.text == "0"
{
answerField.text = theButton.titleLabel.text
}
else
{
answerField.text = answerField.text + theButton.titleLabel.text
}
}
#IBAction func plusTapped(theButton: UIButton) {
// error is talking about the next line
if operaterLabel.text == ""
{
operaterLabel.text = "+"
lastNumber = answerField.text
answerField.text = "0"
}
else
{
enterTapped(nil)
operaterLabel.text = "+"
}
}
#IBAction func minusTapped(theButton: UIButton) {
if operaterLabel.text == ""
{
operaterLabel.text = "-"
lastNumber = answerField.text
answerField.text = "0"
}
else
{
enterTapped(nil)
operaterLabel.text = "-"
}
}
#IBAction func clearTapped(AnyObject) {
answerField.text = "0"
operaterLabel.text = ""
lastNumber = ""
}
#IBAction func enterTapped(AnyObject?) {
var num1 = lastNumber.toInt()
var num2 = answerField.text.toInt()
if !num1 || !num2
{
showError()
return
}
var answer = 0
if operaterLabel.text == "-"
{
var answer = num1! - num2!
}
else if operaterLabel.text == "+"
{
var answer = num1! + num2!
}
else
{
showError()
return
}
answerField.text = "\(answer)"
}
func showError()
{
println("Ther was an error")
}
}

the error refers to the fact that you're accessing the parameter of an optional value when the optional value is set to nil (e.g. accessing answerField.text when answerField is nil), likely one of your two UILabels.
If the line operaterLabel.text == "" is throwing the exception, then your operaterLabel is nil. Verify that you have connected it successfully to the label in your Interface Builder file.

In my case, I was trying to access the labels in a function that I created which was used after the set of a variable.
var something: String {
didSet {
updateUI()
}
}
func updateUI() {
label.text = "Hello"
}
I solved it by:
var something: String
override func viewDidLoad() {
label.text = "hello"
}
My theory is that my function updateUI was accessed before the views and labels were created.

some times the problem that you have initiate view controller before present it like this:
let myViewController = MyViewController()
replace that by
let myViewController = self.storyboard?.instantiateViewController(withIdentifier: "storyboardID") as! MyViewController

check your outlets, I've had this before labels and buttons can just become dis connected (if for instance you have adjusted constraints ect)
a simple re connection can sometimes fix the issue

If you make sure the xib for your cell is no problem,
Then I occur this issue, my error was register the cell method :
1)
self.tableView.register(TerantInfoTabCell.self, forCellReuseIdentifier: "TerantInfoTabCell")
2)
self.tableView.register(UINib(nibName:"TerantInfoTabCell", bundle: nil), forCellReuseIdentifier: "TerantInfoTabCell")
I use the first method, there will appear the issue,then I use the 2) method replace the 1) , so there is no problem here.

I had the exact same error and spent quiet an amount of time debugging it. What #jmduke said is really the key: where does the error occur?
With my particular error, looking at operaterLabel.text == "" led me on the right path. I accessed the operaterLabel.text while the view was not yet fully initialized. In my particular case I set a variable from a different view during a segue and then acted upon that variable being set and updating a label inside the view. However the view was not completely initialized.
Thus my solution was to update the label inside the viewDidLoad() function.

I searched and searched trying to figure out how to solve my similar problem. As others mentioned, I was accessing UI elements before they were initialized. But figuring out why, was the difficult part. Spoiler --> I was using ProfileVC.swift and profileVC.xib
Even though I had all of my connections right in IB, from the parentVC I was calling
let newVC = ProfileVC()
profile.modalPresentationStyle = .custom
present(profile, animated: true, completion:nil)
Since I had different names (caplital 'P' in my swift file and lowercase 'p' in my xib), calling ProfileVC() didn't work as it didn't know to go to the xib I had made. Instead I had to use:
let newVC = ProfileVC.init(nibName: "profileVC", bundle: Bundle.main)
or just rename the xib to have a captial P and I could use my original code
Obviously this is hard to see in stackoverflow as you need to see what you are calling in the parent VC, the names of the files and IB. So hopefully this may be one solution to someone's problem out there even if it doesn't solve Arshia's problem.

That means your storyboard doesn't have a link to your IBOUTLET, please verify

I had this error and my problem was caused by adding a member (let's call it newProperty) to my model class, then trying to run a project that loaded data with NSCoder.decodeObjectForKey(newPropertyKey). During previous testing, I had saved objects without newProperty, so when the app tried to call decodeObjectForKey(newPropertyKey) on my old data, Xcode responded with this error message.

This error usually occurs because we try to change UILabel text after the view is loaded. Remember that UILabels once loaded in the view cannot be changed in any way they can only be set within viewdidload() function. You can check this by putting your text assigning code in the viewDidLoad() function which will set UILabels when loading the view, It will work.
But now if your application is built in such a way that it is setting UILabels after the view is loaded then the only solution is that you will need to create UILabels dynamically/Programatically where ever you want in the code and assign what ever you want because they will be created/instantiated with that text/label.

As #aircraft said you can register your cell this way :
let cellNib = UINib(nibName: "\(CellClass.self)", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "\(CellClass.self)")
this solved the problem with me.

Related

Having trouble initializing variable

I'm trying to initialize a variable in a view controller before that view controller takes over the view, and it seems no matter how I try to initialize it, it doesn't work and the software runs as if the value is the default value. Part of the problem seems to be the view that contains the variable in question is nil when I try to set the variable's value. I don't know why this is. Any help would be appreciated. Thanks! Here is my code:
override func setStartPosition()
{
if sessionNameIndex != nil
{
if let curSession = ShareData.sharedInstance.sessionDataObjectContainer[sessionNames[sessionNameIndex]]
{
initialValue = YesNo(rawValue: (curSession.currentValue))
if mySessionDisplay == nil
{
mySessionDisplay = SessionDisplayView(frame: self.view.frame)
if mySessionDisplay == nil
{
var shouldneverbehere = 0 //Always goes here!
}
else
{
mySessionDisplay.onView(index: 2, sessionName: sessionNames[sessionNameIndex])
mySessionDisplay.curScene.setStartPosition(newValue: val!)
}
}
}
}
}
This function gets called in the following code:
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if let destination = segue.destination as? SessionDisplayViewControllerTwo
{
if let myNames = sender as? [String]
{
destination.sessionNames = myNames
destination.sessionNameIndex = 1
destination.setStartPosition()
}
}
}
Let me know if you need more information. Once again, thanks for your consideration of this matter.
A view controller's views have not yet been loaded in prepareForSegue. As #muescha suggests in his comment, you should set properties in prepareForSegue, and then wait for viewDidLoad or viewWillAppear before you try to install them in your views. I'm not sure why your attempt to manually create your SessionDisplayView is failing, but you should not be trying to create views in prepareForSegue in any case, so the solution is "Don't do that."

Passing data between controllers - unexpectedly found nil while unwrapping an Optional

I am attempting a very simple task of passing data between two view controllers. I have control-dragged the label into the proper class and allowed the segues to populate with the correct data. Upon clicking the row, the prepareForSegue action is as:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "individualChat" {
if let indexPath = tableView.indexPathForSelectedRow {
let friend: Friend
friend = mappedFriends[indexPath.row]
let controller = segue.destinationViewController as! IndividualChatController
controller.friendChat = friend
}
}
}
and into the residing view controller:
import UIKit
class IndividualChatController: UIViewController {
#IBOutlet weak var anotherTestLabel: UILabel!
var friendChat: Friend! {
didSet {
configureView()
}
}
func configureView() {
if let friendChat = friendChat {
anotherTestLabel.text = friendChat.name as? String
}
}
}
Yet, upon clicking the row, the error appears:
fatal error: unexpectedly found nil while unwrapping an Optional value
on line:
anotherTestLabel.text = friendChat.name as? String
How can this be fixed?
Additional Screen Capture:
When you execute some code in prepareForSegue the next view is not loaded yet so all your outlets are still set to nil; because of this when you try to implicitly unwrap the content of anotherTestLabel at
anotherTestLabel.text = friendChat.name as? String
you get that error.
You can check if your label has been loaded and only if that's the case set its text using
anotherTestLabel?.text = friendChat.name as? String
and then manually calling configureView() in viewDidLoad() of IndividualChatController to proper load the label.
The added ? will check if your label is nil, if so nothing will be done, else it will proceed unwrapping the label and setting the text.

Swift: unexpectedly found nil while unwrapping an Optional value While updating a Label

I have a UILabel inside a modelviewcontroller.
What i want to do is change its text on a certain point of my code. The problem is it works in the first point and stops working on the second one, throwing the following error:
unexpectedly found nil while unwrapping an Optional value
I found other questions on the same error but those solutions are not working for me. Maybe I am doing something wrong with the optionals.
Here is the code of my model view controller:
import UIKit
class CheckInViewController: UIViewController {
#IBOutlet weak var test: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
print("Appeared")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("scanViewController") as! ScanViewController
test.text = "Here it works" // FIRST POINT WORKS AND CHANGES THE LABEL
if let qrCode = vc.qrCode{ // vc.qrCode IS AN OPTIONAL
qrRead(qrCode)
vc.qrCode = nil
}
}
func qrRead(qrCode: String) {
print(qrCode)
test.text = "Here it doesnt work" // HERE IT STOPS WORKING
}
You are setting the vc.qrCode to nil directly after passing it to the func qrRead(qrCode: String) function.
Remove this line: vc.qrCode = nil and check if the error persists.
If it does not, as I suspect, nil the var out elsewhere.
Remember using if let, you actually access the underlying instance, not a copy.
As such, when you set vc.qrCode to nil, you are ALSO setting qrCode to nil which causes issues when you try to print it in the qrRead function
Example:
class Person {
}
var a:Person? = Person()
if let some = a
{
print(unsafeAddressOf(some))
print(unsafeAddressOf(a!))
}
Prints:
0x0000000005011ed0
0x0000000005011ed0
Which shows they are the same instance in memory.

Swift : fatal error: unexpectedly found nil and EXC_BAD_INSTRUCTION

I m new to Xcode and i m building a project with a login button. After clicking the login with details in the text field, it will redirect to the second view which is the scroll view controller. However, i got two parts of "Error"
Normally, it work with a normal view controller(login and move to the second view). I have just recreate a view controller to a scroll view controller and it did not work.
By the way, I got a build success but i just got error when i try to "login"
Can anyone explain why i got the thread error and the fatal error?
How can i resolve the problem?
login view Controller
#IBAction func LoginBtn(sender: AnyObject) {
LoginIn()
}
func LoginIn(){
let user = PFUser()
user.username = usernameTF.text!
user.password = passwordTF.text!
PFUser.logInWithUsernameInBackground(usernameTF.text!,
password:passwordTF.text! , block: { (User: PFUser?, Error
:NSError? ) -> Void in
if Error == nil{
dispatch_async(dispatch_get_main_queue()){
let Storyboard = UIStoryboard(name: "Main", bundle: nil)
let MainVC : UIViewController = Storyboard.instantiateViewControllerWithIdentifier("scrollV") as UIViewController
self.presentViewController(MainVC, animated: true, completion: nil)
}
}
else{
NSLog("Wrong!!!!")
}
})
}
Scroll View Controller
import UIKit
class ScrollViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
let V1 : ScrollViewController = ScrollViewController(nibName: "ScrollViewController", bundle: nil)
self.addChildViewController(V1)
self.scrollView!.addSubview(V1.view!)
V1.didMoveToParentViewController(self)
}
You are doing some forced unwrapping, which is not recommended (in general forced stuff in Swift is not recommended), and it will crash your application if the variable being unwrapped is nil. That's why forced unwrap is recommended only when you're 100% sure that you have a valid value in your optional.
In your case, it seems that V1.view! causes the crash, and this might be caused by the fact that V1 didn't successfully loaded from the nib.
Swift has made it very easy to work with nullable values. Just don't force unwrap and use optional binding instead.
#Cristik is correct. Instead of force unwrapping the variable, you should check to see if it is instantiated using the "if let" statement:
if let scrollView = self.scrollView {
if let subView = V1.view {
scrollView.addSubview(subView)
}
}

Can't UnWrap Optional - None Swift

I assure you that i have checked all the answers prior posting this question on Unwrapping an object, but this thing simply does not seem to work for me. I am simply trying to pass on a text value from my cell tapped to the Label on the next screen.
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if(segue.identifier == "detailViewSegue")
{
var DVC:DetailedViewController = segue.destinationViewController as DetailedViewController
let path:NSIndexPath = self.tableView.indexPathForSelectedRow()
var segueRecipeName:String = recipeMgr.RecipeName[path.row] as String
DVC.detailedRecipeLabel.text = segueRecipeName
}
}
The problem occurs at this line -
DVC.detailedRecipeLabel.text = segueRecipeName //Can't UnWrap Optional - None
I know I'm supposed to check the nil value of segueRecipeName before assigning. I do a print check on the console and it clearly is not null. The error occurs only when I'm assigning the value to the 2nd view controller class object. I'm sure this will help others learning Swift :)
DVC.detailedRecipeLabel is nil
Probably it's a IBOutlet that hasn't been loaded yet.
You should add a custom property to your DetailedViewController that will accept your text, save it and then you can assign it to the label in viewDidLoad.
Example:
class DetailedViewController ... {
...
var recipeName: NSString? = nil
...
override func viewDidLoad() -> () {
...
self.detailedRecipeLabel.text = self.recipeName
}
}
DVC.recipeName = segueRecipeName

Resources