从Alamofire捕获数据 [英] Capturing data from Alamofire

查看:154
本文介绍了从Alamofire捕获数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法异步从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 = "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语句在请求返回之前运行。

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. 更新 getBook 异步方法并返回带有完成块/回调的结果

  2. 等待异步调用完成,阻塞当前线程(只要这样就可以了它不是你要阻止的主线程,并且同步返回结果。

  1. Update your getBook method to be asynchronous and return the result with a completion block/callback
  2. Wait for the asynchronous call to complete, blocking the current thread (this is OK as long as it is not the main thread you are blocking), and return the result synchronously.



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 = "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 错误

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 = "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
    }
}

这篇关于从Alamofire捕获数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆