Brent Royal-Gordon
unread,Nov 3, 2015, 5:24:08 PM11/3/15Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to Ishac Dainurry, Swift Language
So, here’s the deal.
NSData.init(contentsOfURL:) is a “failable” initializer. That means it returns an optional NSData—“NSData?”. Thus, your “data” variable is of type NSData?. You can confirm this by Option-Clicking on “data”, which will tell you the type Swift inferred for it.
NSJSONSerialization.JSONObjectWithData’s first parameter is declared to be of type “NSData”. Note that there’s no question mark—the NSData is *not* optional. Passing an optional NSData to a parameter that expects a plain NSData is an error.
So you need to make “data" non-optional. There are a couple different ways to do this. The simplest is to just say “data!” as the parameter, but this will crash if the NSData.init(contentsOfURL:) call fails. Since you’re fetching from an Internet URL, that’s fairly likely to happen (for instance, if someone launches your app while in Airplane Mode), and it’s a bad idea to assume it won’t.
A better idea is to modify your code into something like:
if let nonOptionalData = data {
let decodedJSON = NSJSONSerialization.JSONObjectWithData(nonOptionalData, …
[the other lines that use decodedJSON go here]
}
else {
// Some code that displays an error message, uses cached data, or otherwise handles the error case
}
Even this, though, may be a little bit problematic. When you say NSData(contentsOfURL: url!), that blocks the current thread until the URL is retrieved. When the URL is for a file out on the Internet, like this one is, that can block the current thread for a long time. If this code is run on the main thread, that means your entire app freezes until the data comes in. Even for a small file, that could take up to several minutes on a slow or malfunctioning connection.
To avoid this problem, you’re better off using NSURLSession.dataTaskWithURL(_:completionHandler:). Restructuring your code to do this is somewhat intricate and probably depends on your UI, so I’m not going to try to write example code.
HTH,
--
Brent Royal-Gordon
Architechies