我无法从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或类似名称,并检查是否要在调用者函数上设置bookerror

    要调用该函数,您需要传递一个块来处理响应:
    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/

    10-15 07:52