问题
At some point in my app the user supplies a movie name. The controller will get more info about the movie from OMDB and store it. I run into problems getting converting the JSON from the url into a dictionary. Here's my code:
@IBAction func addMovieButtonPressed(_ sender: Any) {
// get title from the text field and prepare it for insertion into the url
let movieTitle = movieTitleField.text!.replacingOccurrences(of: " ", with: "+")
// get data for the movie the user named
let movieData = getMovieData(movieTitle: movieTitle)
// debug print statement
print(movieData)
// reset text field for possible new entry
movieTitleField.text = ""
}
// function that retrieves the info about the movie and converts it to a dictionary
private func getMovieData(movieTitle: String) -> [String: Any] {
// declare a dictionary for the parsed JSON to go in
var movieData = [String: Any]()
// prepare the url in proper type
let url = URL(string: "http://www.omdbapi.com/?t=\(movieTitle)")
// get the JSON from OMDB, parse it and store it into movieData
URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in
guard let data = data, error == nil else { return }
do {
movieData = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String: Any]
} catch let error as NSError {
print(error)
}
}).resume()
// return the data
return movieData
}
I have tried many variations of the URLSession part that I found on Stackoverflow and I know that the data is successfully fetched:
However I don't know how to properly get at it and turn it into a dictionary I can then use in the rest of my app. The print statement in the IBAction function always returns an empty dictionary.
What am I doing wrong?
回答1:
Look into completion blocks and asynchronous functions. Your getMovieData
is returning before the datatask's completion handler is called.
Your function, instead of returning, will call the completion block passed in and should change to:
private func getMovieData(movieTitle: String, completion: @escaping ([String:Any]) -> Void) {
// declare a dictionary for the parsed JSON to go in
var movieData = [String: Any]()
// prepare the url in proper type
let url = URL(string: "http://www.omdbapi.com/?t=\(movieTitle)")
// get the JSON from OMDB, parse it and store it into movieData
URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in
guard let data = data, error == nil else { return }
do {
movieData = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String: Any]
completion(movieData)
} catch let error as NSError {
print(error)
}
}).resume()
}
来源:https://stackoverflow.com/questions/42425524/parsing-fetched-json-to-dictionary-in-swift-3