我必须在API上搜索一部电影,并在我的桌面视图中返回搜索到的电影。
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)
}
}
//------------------------------------------------
这个名为Movie的类(将在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 }
}
}
然后,我的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)
}
}
})
}
}
首先,什么是闭包,如果我不在这个函数中使用它会发生什么?
现在,我该如何测试这个功能?我在我的AppDelegate中称它为:
print(MovieDAO.getMovies(imdbTitle: "arq"))
但是xcode返回一个错误,说明在调用中缺少一个参数。那么,你能解释一下吗?我读到了它,但我是一个初学者,它仍然让我感到困惑。
哦,我想用搜索过的标题打印一个数组。我几乎可以肯定我的功能没有返回。我该如何调整功能呢?
为了更好地理解,API为搜索的电影提供了这个Json:
{
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;
}
我确实喜欢这个建议并且调用了(在我的AppDelegate上,只是为了测试并看看它是否得到我想要的,在这种情况下,包含标题上的“arq”的电影列表)我的功能如下:
MovieDAO.getMovies(imdbTitle: "arq") {
(movies: [Movie]) in
// Do something with the movies
print(movies)
}
这条绿线有什么问题?
答案 0 :(得分:1)
问题
您尝试调用的函数具有以下方法签名:
getMovies(imdbTitle: String, completionHandler: @escaping (([Movie]) -> ()))
您尝试仅使用第一个参数调用它:imdbTitle
。您看到的错误是因为您从未传递完成处理程序 - 您缺少最后一个参数。
解决方案
更改您的通话以包含完成功能块,如下所示:
MovieDAO.getMovies(imdbTitle: "Title") {
(movies: [Movie]) in
// Do something with the movies
print(movies)
}
答案 1 :(得分:0)
将闭包想象成一堆你想要运行的代码,然后保存为一个变量,然后传递给函数。
这就是你在MoviesDAO中的GetMovies函数调用中所做的事情
static func getMovies(imdbTitle: String, completionHandler: @escaping (([Movie]) -> ())) {
completionHandler参数需要一个代码块,该代码块接受一个Movie对象数组并对其执行某些操作。 (可能在您的情况下打印)。
因为,正在发生的事情是你在问一些API(IMDB),“嘿,我想让你给我一堆名为'arg'的电影”。 IMDB无法立即向您提供该信息,并且您不希望程序的其余部分等待,因此您的GetMovies函数调用要求在获取电影对象数组后运行某些代码。
completionHandler(fetchedMovies)
您已经将您的功能参数命名为有点令人困惑,这可能对您正在阅读的内容没有帮助。你有一些与SearchMoviesOnJSON函数的completionHandler冲突的时髦名字。所以我要重命名你的getMovies函数,但只留下SearchMoviesOnJSON。
static func getMovies(imdbTitle: String, handlerForMovieArray: @escaping (([Movie]) -> ()))
所以不要打电话
print(MovieDAO.getMovies(imdbTitle: "arq"))
你应该做的是定义一个getMovies函数最后调用的闭包(一块代码)。
MovieDAO.getMovies(imdbTitle: "arg", handlerForMovieArray: {
MoviesList in //<-- This is your input.
//Your array of movies that is being passed by the call to "handlerForMovieArray"
//Do some fancy code stuff here. Probably want to loop over MoviesList and print the values you want
})
我希望这有帮助!如果您有更多问题,请联系。