omid
omid

Reputation: 37

swift Xcode: unexpectedly found nil while unwrapping an Optional value (lldb)

when i ran this code, update labels (aLabel and bLabel) perfectly. the viewDidLoad run perfectly, but when i press freshButtonPressed the Xcode show error. the unexpectedly found nil while unwrapping an Optional value appeared on self.aLabel.text = var1 (comment shows the error place). the code of viewDidLoad is same as freshButtonPressed. I couldn't figure out the problem.

I appriciated.

import UIKit

class segView1ViewController: UIViewController {

@IBOutlet weak var dollarUSALabel: UILabel!
@IBOutlet weak var euroLabel: UILabel!



func refreshingData1() {
    println("refreshing ...")

    var dollar2 = ""
    var euro2 = ""

    var arzUrl = NSURL(string: "http://www.arzlive.com")

    if arzUrl != nil {

        let task2 = NSURLSession.sharedSession().dataTaskWithURL(arzUrl!, completionHandler: { (data, response, error) -> Void in

            var urlError = false

            if error == nil {
                //main code
                //parsing url contents

                var arzUrlContent = NSString(data: data, encoding: NSUTF8StringEncoding) as NSString!

                //println(arzUrlContent)


                /////////// Dollar
                var dollarTempArray = arzUrlContent.componentsSeparatedByString("s3_40 price\">")

                //println(dollarTempArray[1])

                if dollarTempArray.count > 0 {

                    var dollarTempArray2 = dollarTempArray[1].componentsSeparatedByString("<td")
                    dollar2 = dollarTempArray2[0] as! String

                    //println(dollar)

                } else {
                    urlError = true
                }


                ////////// Euro
                var euroTempArray = arzUrlContent.componentsSeparatedByString("s3_41 price\">")

                //println(euroTempArray[1])

                if euroTempArray.count > 0 {

                    var euroTempArray2 = euroTempArray[1].componentsSeparatedByString("<td")
                    euro2 = euroTempArray2[0] as! String

                    //println(euro)

                } else {
                    urlError = true
                }

                } else {
                //error handling for web task error
                urlError = true

            }

            dispatch_async(dispatch_get_main_queue()) {
                //checking error
                if urlError == true {

                    //run error func
                    self.showError()
                } else {
                    //update labels here

                    self.dollarUSALabel.text = dollar2
                    self.euroLabel.text = euro2


                }
            }

        })

        //resume task
        task2.resume()

    } else {
        // error handler 
        showError()
    }

    ////////end of func
}


    func showError() {    
        //some error handling code...
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        self.dollarUSALabel.text = "0"
        self.euroLabel.text = "0"
        var dollar = ""
        var euro = ""

        // arzlive url
    var arzUrl = NSURL(string: "http://www.arzlive.com")

    if arzUrl != nil {

        let task1 = NSURLSession.sharedSession().dataTaskWithURL(arzUrl!, completionHandler: { (data, response, error) -> Void in

            var urlError = false

            if error == nil {
                //main code
                //parsing url contents

                var arzUrlContent = NSString(data: data, encoding: NSUTF8StringEncoding) as NSString!

                //println(arzUrlContent)


                /////////// Dollar
                var dollarTempArray = arzUrlContent.componentsSeparatedByString("s3_40 price\">")

                //println(dollarTempArray[1])

                if dollarTempArray.count > 0 {

                    var dollarTempArray2 = dollarTempArray[1].componentsSeparatedByString("<td")
                    dollar = dollarTempArray2[0] as! String

                    //println(dollar)

                } else {
                    urlError = true
                }


                ////////// Euro
                var euroTempArray = arzUrlContent.componentsSeparatedByString("s3_41 price\">")

                //println(euroTempArray[1])

                if euroTempArray.count > 0 {

                    var euroTempArray2 = euroTempArray[1].componentsSeparatedByString("<td")
                    euro = euroTempArray2[0] as! String

                    //println(euro)

                } else {
                    urlError = true
                }


            } else {
                //error handling for web task error
                urlError = true

            }

            dispatch_async(dispatch_get_main_queue()) {
                //checking error
                if urlError == true {

                    //run error func
                    self.showError()
                } else {
                    //update labels here

                    self.dollarUSALabel.text = dollar
                    self.euroLabel.text = euro

                }
            }

        })

        //resume task
        task1.resume()

    } else {
        // error handler 
        showError()
    }

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

Upvotes: 0

Views: 495

Answers (1)

BaseZen
BaseZen

Reputation: 8718

Ran the project. Could not reproduce the problem. Two issues though:

-- Your code doesn't compile because the dollarTempArrays are not declared anywhere. Please submit something that compiles.

-- You have an array indexing logic error, because you're checking if the count is at least one, but then indexing the second element (at index 1, not index 0, where you should be checking)

Please submit a version that compiles and ideally a website that provides the data. Although, I hardcoded values in place of var1 and var2 and the UI updated no problem.

Since your crash is out of sync with your posted code, I'll bet other things are out of sync in your environment. Quit Xcode & iOS Simulator, get back in, do a clean build, verify your Outlets, and post what you really have now.

Calling your variables var12345 is both sadistic and masochistic, so start abandoning that practice now, even in test code. It's much harder to help with that kind of blatant violations of good practice.

** LATER THAT DAY **

I put it through the professional programmer descrambler and the following resulted. What you're trying to do is not complicated and need not be long. Please observe style, abstraction, efficiency, as well as bug fixes. I just tested this in Xcode 6.4 / Swift 1.2 / iOS simulator on iPhone 6.

import UIKit

class CurrencyViewController: UIViewController {
    @IBOutlet weak var dollarUSALabel: UILabel!
    @IBOutlet weak var euroLabel: UILabel!
    let dataURL = "http://www.arzlive.com"

    func refreshData() {
        println("refreshing ...")
        if let arzUrl = NSURL(string: dataURL) {
            let task2 = NSURLSession.sharedSession().dataTaskWithURL(arzUrl)
                { [unowned self]
                    (data, response, error) -> Void in
                    if let d = data, arzUrlContent = NSString(data: d, encoding: NSUTF8StringEncoding) {            
                        var dollar: String?
                        var euro: String?
                        let dollarTempArray = arzUrlContent.componentsSeparatedByString("s3_40 price\">")
                        if dollarTempArray.count >= 2 {
                            let dollarTempArray2 = dollarTempArray[1].componentsSeparatedByString("<td")
                            dollar = dollarTempArray2[0] as? String
                        }
                        let euroTempArray = arzUrlContent.componentsSeparatedByString("s3_41 price\">")
                        if euroTempArray.count >= 2 {
                            var euroTempArray2 = euroTempArray[1].componentsSeparatedByString("<td")
                            euro = euroTempArray2[0] as? String
                        }
                    }
                    dispatch_async(dispatch_get_main_queue()) {
                        self.dollarUSALabel.text = dollar ?? "Could not get dollars!"
                        self.euroLabel.text = euro ?? "Could not get euros!"
                    }
            }
            task2.resume() // START task ('resume' is misleading)
        }
        else {
            showError("Could not access \(dataURL)")
        }
    } /* end of refreshData */

    /* TODO for you: Use UIAlertController to inform the user */
    func showError(message: String) {
        println(message)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        refreshData()
    }
}

Upvotes: 2

Related Questions