NSURLConnection not calling methods (worked the first time)

647 views Asked by At

So I'm using an NSURLConnection to get JSON data from a website, it works and I store the data in a search controller/ table view. Now when a user clicks on a cell in the view I want to segue to a new view, and load another set of JSON data from a website. However, in this new view the connection never runs the methods. Here is what I'm doing both times (each in a different view controller)

func startConnection(){
    var url: NSURL = NSURL(string: self.formatted)!
    var request: NSURLRequest = NSURLRequest(URL: url)
    var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)!
    connection.scheduleInRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode) // I tried to put this in based on suggestions from searches I did, it didn't help
    connection.start()
}

func connection(connection: NSURLConnection!, didReceiveData data: NSData!){
    self.data.appendData(data)

}

func connectionDidFinishLoading(connection: NSURLConnection!){
    var err: NSError
    var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary
    println(jsonResult)

}

From breakpoints it looks like it never runs:

func connection(connection: NSURLConnection!, didReceiveData data: NSData!)

I'm calling startConnection() in ViewDidLoad

1

There are 1 answers

2
Rob On BEST ANSWER

Implement connection:didFailWithError:, too. See what it reports. Without that, you have no way of knowing why it failed.

func connection(connection: NSURLConnection, didFailWithError error: NSError) {
    println("connection error = \(error)")
}

Also, in didReceiveData (and the rest of these methods), the NSURLConnection parameter is not optional. Back before these were audited, they may have used implicitly unwrapped optionals, but no longer. Double check your method signatures. If you actually define your class as explicitly conforming to NSURLConnectionDataDelegate and NSURLConnectionDelegate, you should get warnings about this.


As an aside, you are not using the NSError variable in connectionDidFinishLoading that could be populated if JSONObjectWithData encountered any problems parsing the response. So supply that NSError variable to JSONObjectWithData, and you can now diagnose any errors that occur during the parsing. Hopefully you will not have any parsing errors, but if you do, having the NSError reference would be very useful.

Also, you don't need that startImmediately of false and manually scheduling it on the main run loop. You only do that if you are initiating this connection from a background thread. But since you're calling this from viewDidLoad, that's unnecessary.

So it might end up looking like:

func startConnection() {
    data = NSMutableData()
    let url = NSURL(string: formatted)
    let request = NSURLRequest(URL: url!)
    NSURLConnection(request: request, delegate: self)
}

func connection(connection: NSURLConnection, didReceiveData data: NSData) {
    self.data.appendData(data)
}

func connectionDidFinishLoading(connection: NSURLConnection) {
    var error: NSError?
    if let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error) as? NSDictionary {
        println(jsonResult)
    } else {
        println("parsing error = \(error)")
        let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
        println("responseString = \(responseString)")
    }
}

func connection(connection: NSURLConnection, didFailWithError error: NSError) {
    println("connection error = \(error)")
}

By the way, you might also want to implement didReceiveResponse as that can also provide information about any server errors you may receive:

func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) {
    if let httpResponse = response as? NSHTTPURLResponse {
        let statusCode = httpResponse.statusCode

        if statusCode != 200 {
            println("expected HTTP response of 200; received \(statusCode)")
            println(httpResponse)
        }
    } else {
        println("expected HTTP response; but didn't get any")
    }
}