我无法从Alamofire请求中异步获取数据。
class BookGetter {
static let instance = BookGetter()
func getBook(bookId: String) -> Book {
let rootUrl = "https://www.someusefulbookapi.com/bookid=?"
let url = rootUrl + bookId
var title = ""
Alamofire.request(.GET, url).response { response in
let jsonDict = JSON(data: response.2!)
title = String(jsonDict["items"][0]["volumeInfo"]["title"])
}
let book = Book(title: title)
print(book.title)
return book
}
}
print(book.title)
的输出是""
,据我了解,这是因为print语句在请求返回之前正在运行。我如何使
book
实例仅在使用请求中的数据实例化时返回? 最佳答案
您遇到的问题是您正在调用异步方法并期望同步返回结果。执行代码后,getBook
函数完成并返回,即使GET
请求尚未完成。
基本上,您有两种选择:
getBook
方法更新为异步方法,并返回带有完成块/回调的结果1.将您的方法更新为异步的
为此,必须在阻止/回调函数上返回结果。
class BookGetter {
static let instance = BookGetter()
func getBook(bookId: String, complete: (book: Book?, error: NSError?) -> Void) {
let rootUrl = "https://www.someusefulbookapi.com/bookid=?"
let url = rootUrl + bookId
var title = ""
Alamofire.request(.GET, url).response { request, response, data, error in
// TODO: You should check for network errors here
// and notify the calling function and end-user properly.
if error != nil {
complete(book: nil, error: error as? NSError)
return
}
let jsonDict = JSON(data: response.2!)
title = String(jsonDict["items"][0]["volumeInfo"]["title"])
let book = Book(title: title)
print(book.title)
complete(book: book, error: nil)
}
}
}
如上述代码中所述,理想情况下,您应该处理回调响应中的错误(包括解析JSON时的异常)。处理后,您可以将回调参数更新为
(book: Book?, error: NSError?) -> Void
或类似名称,并检查是否要在调用者函数上设置book
或error
。要调用该函数,您需要传递一个块来处理响应:
BookGetter.instance.getBook("bookID") { (book, error) in
if error != nil {
// Show UIAlertView with error message (localizedDescription)
return
}
// Update User Interface with the book details
}
2.等待异步调用完成
如上所述,仅当您在后台线程上运行此代码时,这才是一个好主意。阻止后台线程是可以的,但是绝不能阻止图形应用程序上的主线程,因为它将冻结用户界面。如果您不知道阻止的含义,请使用选项#1。
class BookGetter {
static let instance = BookGetter()
func getBook(bookId: String) -> Book {
let rootUrl = "https://www.someusefulbookapi.com/bookid=?"
let url = rootUrl + bookId
var title = ""
let semaphore = dispatch_semaphore_create(0)
Alamofire.request(.GET, url).response { response in
let jsonDict = JSON(data: response.2!)
title = String(jsonDict["items"][0]["volumeInfo"]["title"])
dispatch_semaphore_signal(semaphore)
}
//Wait for the request to complete
while dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW) != 0 {
NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate(timeIntervalSinceNow: 10))
}
let book = Book(title: title)
print(book.title)
return book
}
}
关于ios - 从Alamofire捕获数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33129943/