我无法异步从Alamofire请求中检索数据。
I'm having trouble retrieving data from my Alamofire request asynchronously.
class BookGetter { static let instance = BookGetter() func getBook(bookId: String) -> Book { let rootUrl = "www.someusefulbookapi/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语句在请求返回之前运行。
The output of print(book.title) is "", and I understand this is because the print statement is running before the request returns.
如何获得书只有在用请求中的数据实例化时才返回实例?
How do I get the book instance to be returned only when it is instantiated with the data from the request?
推荐答案你遇到的问题是您正在调用异步方法并期望同步返回结果。执行代码后,即使 GET 请求完成, getBook 函数也会完成并返回。
The problem you have is that you are calling an asynchronous method and expecting to return the result synchronously. When your code is executed, the getBook function completes and returns before even the GET request has complete.
基本上,您有两种选择:
Basically, you have two options:
1。将您的方法更新为异步
为此,您必须在块/回调函数上返回结果。
1. Update your method to be asynchronous
To do this, you must return the result on a block/callback function.
class BookGetter { static let instance = BookGetter() func getBook(bookId: String, complete: (book: Book?, error: NSError?) -> Void) { let rootUrl = "www.someusefulbookapi/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 或错误 。
As mentioned in the above code, ideally you should handle errors in the callback response (including exceptions while parsing the JSON). Once handled, you can update the callback parameters to (book: Book?, error: NSError?) -> Void or similar, and check for book or error to be set on the caller function.
要调用该函数,您需要传递一个块来处理响应:
To call the function, you need to pass a block to handle the response:
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。
2. Wait for the asynchronous call to complete
As mentioned above, this is a good idea only if you were running this code on a background thread. It is OK to block background threads, but it is never OK to block the main thread on a graphic application, as it will freeze the user interface. If you do not know what blocking means, please use the option #1.
class BookGetter { static let instance = BookGetter() func getBook(bookId: String) -> Book { let rootUrl = "www.someusefulbookapi/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 } }更多推荐
从Alamofire捕获数据
发布评论