cannot invoke 'JJSONObjectWithData'

6 views
Skip to first unread message

Ishac Dainurry

unread,
Nov 3, 2015, 4:59:25 PM11/3/15
to Swift Language
sory my english is bad

anyone can help me for this error..
please help me, i am new for swift language,,

thanks for all

Jens Alfke

unread,
Nov 3, 2015, 5:10:56 PM11/3/15
to Ishac Dainurry, Swift Language
The error message shows that the first argument is of type ‘NSData?’ — it’s an optional. But the method you’re calling takes a non-optional NSData. So you need to check ‘data' for nil and get the real NSData first. One way is to use “if let”:
if let data = NSData(contentsOfURL:url!) {
…rest of code…
}

Or in Swift 2 you can use ‘guard let’:
guard let data = NSData(contentsOfURL:url!) else {
return false // or however else you want to fail
}
…rest of code...

—Jens

Brent Royal-Gordon

unread,
Nov 3, 2015, 5:24:08 PM11/3/15
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

Reply all
Reply to author
Forward
0 new messages