I have to search a movie on the API and return on my table view the movies searched.
Swift 3 - xcode 8
func searchMoviesOnJson(imdbTitle: String, completionHandler: @escaping (Dictionary<String, Any>?) -> ()) {
let urlByName: String = "https://www.omdbapi.com/?s=\(imdbTitle)&type=movie"
//returns a list of movies that contains the title searched
//------------------------------------------------
Alamofire.request(urlByName).responseJSON {
response in
switch response.result {
case .success(let value):
let moviesJSON = value
completionHandler(moviesJSON as? Dictionary<String, Any>)
case .failure(_):
completionHandler(nil)
}
}
//------------------------------------------------
This class called Movie (that will be searched on the API):
class Movie {
var poster: String?
var title : String?
var year : String?
var imdbID: String?
init(poster: String?, title: String?, year: String?, imdbID: String?) {
if let isPoster = poster { self.poster = isPoster }
else { self.poster = nil }
if let isTitle = title { self.title = isTitle }
else { self.title = nil }
if let isYear = year { self.year = isYear }
else { self.year = nil }
if let isImdbID = imdbID { self.imdbID = isImdbID }
else { self.imdbID = nil }
}
}
And then, my DAO:
class MovieDAO {
//Search By Title
static func getMovies(imdbTitle: String, completionHandler: @escaping (([Movie]) -> ())) {
searchMoviesOnJson(imdbTitle: imdbTitle, completionHandler: {
newMoviesJSON in
if let moviesJSON = newMoviesJSON {
if moviesJSON["Error"] != nil { return }
else {
//casting
let arrayOfMovies: [[String : String]] = newMoviesJSON!["Search"] as! [[String : String]]
var fetchedMovies = [Movie]()
for eachFetchedMovie: [String : String] in arrayOfMovies {
var poster: String?
var title : String?
var year : String?
var imdbID: String?
if let isPoster = eachFetchedMovie["Poster"] { poster = isPoster }
else { poster = nil }
if let isTitle = eachFetchedMovie["Title"] { title = isTitle }
else { title = nil }
if let isYear = eachFetchedMovie["Year"] { year = isYear }
else { year = nil }
if let isImdbID = eachFetchedMovie["imdbID"] { imdbID = isImdbID }
else { imdbID = nil }
let movie: Movie = Movie(poster: poster, title: title, year: year, imdbID: imdbID)
fetchedMovies.append(movie)
}
completionHandler(fetchedMovies)
}
}
})
}
}
First of all, what is a closure and what would happen if I don't use it in this functions?
Now, how can I test this function? I call it in my AppDelegate like:
print(MovieDAO.getMovies(imdbTitle: "arq"))
But the xcode returns an error saying that is missing a parameter in the call. So, can you explain this to me? I read about it but I'm a beginner and it's still confusing to me.
Oh, I would like to print an array with the searched title. I'm almost sure that my function is not returning that. How can I adapt the function to do that?
Just for better comprehension, the API gives this Json for the movie searched:
{
Response = True;
Search = (
{
Poster = "https://images-na.ssl-images-amazon.com/images/M/MV5BMjAxODQ2MzkyMV5BMl5BanBnXkFtZTgwNjU3MTE5OTE@._V1_SX300.jpg";
Title = ARQ;
Type = movie;
Year = 2016;
imdbID = tt5640450;
},
{
Poster = "N/A";
Title = Arq;
Type = movie;
Year = 2011;
imdbID = tt2141601;
},
{
Poster = "N/A";
Title = "A.R.Q.";
Type = movie;
Year = 2015;
imdbID = tt3829612;
}
);
totalResults = 3;
}
I did like the suggestion and called (on my AppDelegate, just for test and see if it getting what I want, in this case, a list of the movies that contains the "arq" on title) my function like this:
MovieDAO.getMovies(imdbTitle: "arq") {
(movies: [Movie]) in
// Do something with the movies
print(movies)
}
What is wrong with this line that is in green?
The Problem
The function you are trying to call has a method signature like:
getMovies(imdbTitle: String, completionHandler: @escaping (([Movie]) -> ()))
You are trying to call it with just the first parameter: imdbTitle
. The error you are seeing is because you never pass in the completion handler- you are missing the last parameter.
The Solution
Change your call to include the completion block, like so:
MovieDAO.getMovies(imdbTitle: "Title") {
(movies: [Movie]) in
// Do something with the movies
print(movies)
}