Andyopf Andyopf - 20 days ago 13
Swift Question

I cannot fix EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) in Swift xcode 8.1 on Json

I am studying the swift and I update the xcode to current version (8.1). So the source that I saved was changed. When I ran the code. It cracked and I cannot fixed it. It showed "EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)" on the last line. This is a code that I have studied from web.
Thank you very much.

let urlString = "http://swapi.co/api/people/1/"
let session = URLSession.shared
let url = URL(string: urlString)!

session.dataTask(with: url, completionHandler: { (data: Data?, response:URLResponse?, error: NSError?) -> Void in

if let responseData = data {

do {
let json = try JSONSerialization.jsonObject(with: responseData, options: JSONSerialization.ReadingOptions.allowFragments)

if let dict = json as? Dictionary<String, AnyObject> {

if let name = dict["name"] as? String, let height = dict["height"] as? String, let birth = dict["birth_year"] as? String, let hair = dict["hair_color"] as? String {

let person = SWPerson(name: name, height: height, birthYear: birth, hairColor: hair)

print(person.name)
print(person.height)
print(person.hairColor)
print(person.birthYear)

if let films = dict["films"] as? [String] {
for film in films {
print(film)
}
}

}
}


} catch {
print("Could not serialize")
}
}
} as! (Data?, URLResponse?, Error?) -> Void) .resume()

Answer

You can save much time if you simply read the documentation

  • Press ⇧⌘0 (zero, not O)
  • Type dataTask, select dataTask(with:completionHandler:) and press return.

You will get

func dataTask(with url: URL, 
     completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask

Do you see the slightly difference in the error parameter?

So the correct syntax in your code is

session.dataTask(with: url, completionHandler: { (data: Data?, response:URLResponse?, error: Error?) -> Void in
...
}).resume()

There is no type cast at the end.

Further the type annotations in the completion block are not needed because the compiler infers the types. The error doesn't occur if you just write

session.dataTask(with: url, completionHandler: { (data, response, error) in
...
}).resume()

The shortest form is using the trailing closure syntax

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