从Alamofire捕获数据

ray*_*ohn 1 asynchronous ios swift alamofire

我无法异步从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
    }
}
Run Code Online (Sandbox Code Playgroud)

输出print(book.title)"",我明白这是因为print语句在请求返回之前运行.

如何book仅在使用请求中的数据实例化时才能返回实例?

Ene*_*nso 10

您遇到的问题是您正在调用异步方法并期望同步返回结果.执行代码时,getBook函数完成并在GET请求完成之前返回.

基本上,您有两种选择:

  1. 将您的getBook方法更新为异步,并使用完成块/回调返回结果
  2. 等待异步调用完成,阻塞当前线程(只要它不是你阻塞的主线程就可以了),并同步返回结果.

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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如上面的代码所述,理想情况下,您应该处理回调响应中的错误(包括解析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
}
Run Code Online (Sandbox Code Playgroud)

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
    }
}
Run Code Online (Sandbox Code Playgroud)