Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS Build a Weather App with Swift (Retired) Displaying Our Weather Data Connecting the UI to Our Model

Vittorio Somaschini
Vittorio Somaschini
33,371 Points

Can't make the network call here

Hello Pasan Premaratne and hello everyone.

I am getting into troubles here as my code does not make the network call (while it has worked so far and I have been able to make 13 calls as per forecast.io app dashboard).

After spending sometime debugging my code, I have been able to locate the issue somewhere even before the asynchronous task code (pretty weird as I don' t remember we touched this code after creating it).

So, I moved to a playground to test a few things out. I thought this would be better than going back to the right course video and check the error; and now my question is:

let baseURL = NSURL(string:"https://api.forecast.io/forecast/\(apiKey)/37.8267,-122.423")
let weatherData = NSData.dataWithContentsOfURL(baseURL, options: nil, error: nil)

Shouldn't this code already be enough to make the network call? I am getting the error here and I can't understand why.

I know it is in the main thread and is not good, but I have made it as simple as possible only to try to find out my mistake. Clearly the apiKey let is there I simply have not pasted it here.

Any ideas would be much appreciated, for now it turns out I am much better at creating bugs than I am at coding :D

TY

Vittorio

9 Answers

Kai Schuerrer
Kai Schuerrer
10,830 Points

One problem I currently see is your forecastURL. You are creating a url relative to baseURL but you still have the baseURL attached which will result in something like:

https://api.forecast.io/forecast/a784745146b40822807d24071cf9dfc1/https://api.forecast.io/forecast/a784745146b40822807d24071cf9dfc1/37.8267,-122.423

instead it should be

let baseURL = NSURL(string:"https://api.forecast.io/forecast/\(apiKey)/")
    let forecastURL = NSURL(string: "37.8267,-122.423", relativeToURL: baseURL)

Did you check fetching some basic URL like google or something else to check if the status code is 200 or if some other error occurs? With this you could at least check if internet connection is your problem. Else you could recheck your API key.

Kai Schuerrer
Kai Schuerrer
10,830 Points

What kind of error message are you getting? I just tried the code and it works fine, I guess the error is somewhere else, can you give us some more information?

Kai Schuerrer
Kai Schuerrer
10,830 Points

Yes exactly, worked just fine, even in a new created playground using the following code:

let apiKey : String     =   "MY_API_KEY"
let baseURL = NSURL(string:"https://api.forecast.io/forecast/\(apiKey)/37.8267,-122.423")
let weatherData = NSData.dataWithContentsOfURL(baseURL, options: nil, error: nil)

println(weatherData)

let jsonResponse : AnyObject? = NSJSONSerialization.JSONObjectWithData(weatherData, options: nil, error: nil)
println(jsonResponse)

I'm getting a perfect valid json response at the end. Can you show me the whole source of the file?

Vittorio Somaschini
Vittorio Somaschini
33,371 Points

UPDATE

I don't know how I did it exactly but I managed to have the Stormy App work as in the teacher's video. I would say my code is exactly the same as it was before creating the thread . I know this sound like a really stupid sentence, but the only chance that I have made is resetting the apiKey and restarting my mac. Still I haven't managed to sort out that thing with the playground code that the nice Kai Schuerrer provided.

For now I thank him so much for the help. It made me accomplish the relevant needed tasks and I can move on without throwing my computer out of the window! ;)

Vittorio Somaschini
Vittorio Somaschini
33,371 Points

I am not getting a particular error, simply the error which is the 2 line code that I have pasted. It returns the error that I am declaring on the second line.

What do you mean it worked for you? Did those 2 lines of code create the constant weatherData and downloaded the url content Kai Schuerrer ?

Vittorio Somaschini
Vittorio Somaschini
33,371 Points

Thank you Kai Schuerrer for your effort.

My complete code is:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    let baseURL = NSURL(string:"https://api.forecast.io/forecast/\(apiKey)/")
    let forecastURL = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)/37.8267,-122.423", relativeToURL: baseURL)

    let sharedSession = NSURLSession.sharedSession()
    let downloadTask: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(forecastURL, completionHandler: { (location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in

        if (error == nil) {
            let dataObject = NSData(contentsOfURL: location)
            let weatherDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataObject, options: nil, error: nil) as NSDictionary

            let currentWeather = Current(weatherDictionary: weatherDictionary)
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.temperatureLabel.text = "\(currentWeather.temperature)"
                self.iconView.image = currentWeather.icon!
                self.currentTimeLabel.text = "At \(currentWeather.currentTime!) it is"
                self.humidityLabel.text = "\(currentWeather.humidity)"
                self.precipitationLabel.text = "\(currentWeather.precipProbability)"
                self.summaryLabel.text = "\(currentWeather.summary)"
            })

        }
    })

    downloadTask.resume()

}

But I do not think the problem is in there.

I have just tried to use your new playground's code and stil I get nil: which is the error that we fill in the dataWithContentsOfURL line.

It seems to me that my xcode just does not communicate with the internet anymore: I have just used your brand new code in a new playground and still same problem as before.

It is not a matter of asynchronous task or related stuff. I can't explain nor find out why the 3 simple lines of code in the playground can't lead to the network call.

Vittorio Somaschini
Vittorio Somaschini
33,371 Points

Oh sorry Kai Schuerrer

The forecastURL was like that because of the many tries I have tried and I left in that extra string and I apologize for confusion.

But even if it is good know I still have problems. So the problem is not in there.

The fact that your playground code (just copied and pasted into a playground from your reply and changing the apiKey (literally filling it into the string without even caring about security)) returns nil is crazy to me. I really can't understand this behavior.

Now I have restarted my computer and I seem to be getting some network call (as the api dashboard shows) and I will investigate it now. But My main question is now about that simple playground code that works for you and not for me.

I have tried to reset the apiKey also but still nothing which looks surprisingly incredible to me as now the only difference between my code in the playground and yours is the apiKey. I haven't literally touched anything apart from copying and pasting the string into the apiKey constant ...

Kai Schuerrer
Kai Schuerrer
10,830 Points

Great! Really glad you got it working now. Keep it up!

Just wanted to add that this affected me too and restarting the computer fixes it!