zantuja
zantuja

Reputation: 211

Swift URL Response is nil

I have created a custom DataManager class. Inside it I want to fetch data in a method and return an NSData object to convert to JSON afterwards.

I have tried to get the data using the completionHandler but no luck:

class func fetchData() -> NSData? {
    var session = NSURLSession.sharedSession(),
        result = NSData?()
    let DataURL : NSURL = NSURL(string: "http://...file.json")!

    let sessionTask = session.dataTaskWithURL(DataURL, completionHandler: { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
        result = data
    })
    sessionTask.resume()
    return result
}

Upvotes: 1

Views: 2622

Answers (1)

Rob
Rob

Reputation: 437552

The dataTask runs asynchronously. That means that the completion handler closure will not be called by the time you return from fetchData. Thus, result will not have been set yet.

Because of this, you should not try to retrieve data synchronously from an asynchronous method. Instead, you should employ an asynchronous completion handler pattern yourself:

class func fetchData(completion: @escaping (Data?, Error?) -> Void) {
    let session = URLSession.shared
    let url = URL(string: "http://...file.json")!

    let task = session.dataTask(with: url) { data, response, error in
        completion(data, error)
    }
    task.resume()
}

And you'd call it like so:

MyClass.fetchData { data, error in
    guard let data = data, error == nil else {
        print(error ?? "Unknown error")
        return
    }

    // use `data` here; remember to dispatch UI and model updates to the main queue
}

// but do not try to use `data` here

...

FYI, for the original pre-Swift 3 syntax, see previous revision of this answer.

Upvotes: 1

Related Questions