-2

I keep getting this error :

fatal error: unexpectedly found nil while unwrapping an Optional value

and cannot figure out how to debug it!

Here's my code :

func readCSV() -> Array<String> {

    // Creates a new array of strings
    var csvArray : Array<String> = Array<String>()

    if let url: NSURL = NSURL(string : "URLFROMCSV" ) {
        // Creates an Input Stream that will load the datas from our URL
        let data :NSData! = NSData(contentsOfURL: url)!
            let stream : NSInputStream! = NSInputStream(data: data)

            // Opens the receiving stream
            stream.open()

            // Sets a buffer with a given size size
            let bufferSize = 1024
            var buffer  = Array <UInt8>(count: bufferSize, repeatedValue: 0)

            // String variable initialization
            var csvFullString : String = ""

            // While the stream receives datas, parses datas, convert them into strings and then concatenate them into one big string
            while (stream.hasBytesAvailable) {

                let readSize = stream.read(&buffer, maxLength: bufferSize)
                let csvRaw = NSString (bytes: &buffer, length: readSize, encoding: NSUTF8StringEncoding)
                let csvString = csvRaw as String!

                csvFullString = csvFullString + csvString

            }

            // Fills the array with each strings. Separation between strings is made when a Θ character is parsed
            csvArray = csvFullString.componentsSeparatedByString("Θ")

            // Delete each null string
            for(var i = 0 ; i < csvArray.count; i++) {
                if(csvArray[i] == "") {

                    csvArray.removeAtIndex(i)

                }
            }
        }

    return csvArray

}

After searching on the web, I'm pretty sure it has something to do with unwrapping elements but the fact is when I debug it, i don't get any nil value anywhere.

PS: Would like to upload a screen but can't because i don't have 10 reputation, so bad!

Thanks in advance!

EDIT : Line let data :NSData! = NSData(contentsOfURL: url)! got the error. Terry

1 Answers1

0

You're probably creating the error in one of these two lines (though it may show up later):

let data :NSData! = NSData(contentsOfURL: url)!
let stream : NSInputStream! = NSInputStream(data: data)

You're assigning an optional value to an implicitlyUnwrappedOptional type and then using it without checking if you have a valid value.

This is why if let exists. It's a little funny that you've started to indent as if you're using if let but aren't.

Try this instead:

if let url = NSURL(string : "http://gorillaapplications.com/etablissements.csv" ) {

    // Creates an Input Stream that will load the datas from our URL
    if let data = NSData(contentsOfURL: url) {
        let stream = NSInputStream(data: data)
        stream.open()
        // rest of your code here
    }
    else {
        println("Didn't get a data object")
    }
}
else {
    println("Didn't get a URL object")
}

You really need to grasp Optionals for Swift. I'd recommend reading my Optionals chapter in this iBook: https://itunes.apple.com/us/book/swift-optionals-generics-for/id943445214?mt=11&uo=4&at=11lMGu

Update:

Since you added a bit more in your comments above, you're saying you get the error on this line: let data: NSData! = NSData(contentsOfURL: url)!. This is because of the ! at the end, which tells Swift you're sure that this function will return a valid value, so just use it, without checking if it's nil first. In your case, the function is returning nil and so your app crashes. Using the sample code I've provided above, you'll see that you'll no longer get a crash, but your code will execute the "Didn't get a data object" line. You'll need to correctly handle the case where you can't load data from that URL.

Dave Wood
  • 13,143
  • 2
  • 59
  • 67
  • Thank you for answering Dave. The problem I have with the example code you gave me is that it says that the bound value in a conditional binding must be of optional type when it comes to if let stream = NSInputStream(data: data) so I can't run it as it, I have to modify it to a non conditional binding but it keeps getting me errors. By the way thank you for the answer, as a beginner I'm really happy to hear from advanced users. – Terry Vogelsang Mar 24 '15 at 01:05
  • @TerryVogelsang Ah sorry, `NSInputStream` doesn't return an optional, fixed the sample code for you. – Dave Wood Mar 24 '15 at 01:09
  • Ok thank you! So now I get the message "didn't get a data object" it doesn't crash my app anymore but I still have no idea why the data object is not creating, the url is a csv file and appears as it when i hover the variable url and click on the eye. – Terry Vogelsang Mar 24 '15 at 01:15
  • @TerryVogelsang Well that's a different question, one you could create on StackOverflow. When I run that code in a playground, it does load the data from your URL. Is it possible you have a firewall or some other network issue preventing you from accessing the URL from your test device? It is connected via Wifi etc? Try executing `curl http://gorillaapplications.com/etablissements.csv` in a terminal window on your machine to ensure you see what you think you'll see. – Dave Wood Mar 24 '15 at 01:25
  • I get the thing i want when i run this command in mac terminal but i don't know why i doesn't work in Xcode. Playground also outputs me the didn't get a data object string though... Sooner in the afternoon it worked but since I finished the class, i doesn't work anymore. weird... – Terry Vogelsang Mar 24 '15 at 01:35
  • Just restarted my computer and it works! I have no idea where it was coming from but it works perfectly now! Thank you so much!!! – Terry Vogelsang Mar 24 '15 at 01:50
  • Excellent. If the answer helped, please don't forget to up vote it! – Dave Wood Mar 24 '15 at 01:53