iosswiftnsdatanullnsinputstream

Can't figure out why I get a fatal error: unexpectedly found nil while unwrapping an Optional value


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


Solution

  • 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.