Swift: Как вернуть значение для цикла с использованием firebase? [Дубликат]

Используйте функцию callback() внутри успеха foo(). Попробуйте таким образом. Это просто и легко понять. & nbsp;

var lat = "";
var lon = "";
function callback(data) {
    lat = data.lat;
    lon = data.lon;
}
function getLoc() {
    var url = "http://ip-api.com/json"
    $.getJSON(url, function(data) {
        callback(data);
    });
}

getLoc();
48
задан Mark Tyers 8 August 2014 в 13:28
поделиться

6 ответов

Вы можете передать обратный вызов и вызвать обратный вызов внутри асинхронного вызова

примерно так:

class func getGenres(completionHandler: (genres: NSArray) -> ()) {
    ...
    let task = session.dataTaskWithURL(url) {
        data, response, error in
        ...
        resultsArray = results
        completionHandler(genres: resultsArray)
    }
    ...
    task.resume()
}

, а затем вызвать этот метод:

override func viewDidLoad() {
    Bookshop.getGenres {
        genres in
        println("View Controller: \(genres)")     
    }
}
61
ответ дан Alexey Globchastyy 5 September 2018 в 08:29
поделиться

Swiftz уже предлагает Future, который является основным строительным блоком Promise. Будущее - это обещание, которое не может потерпеть неудачу (все термины здесь основаны на интерпретации Scala, , где Promise является монадой ).

https: // github. com / maxpow4h / swiftz / blob / master / swiftz / Future.swift

Надеюсь, что в какой-то момент мы сможем написать его в полной версии в стиле Скала (я могу написать это сам в какой-то момент; Конечно, другие PR будут приветствоваться, это не так сложно, если будущее уже на месте).

В вашем конкретном случае я, вероятно, создаю Result<[Book]> (на основе версии Александроса Салазара Result [/ д2]). Тогда ваша сигнатура метода будет:

class func fetchGenres() -> Future<Result<[Book]>> {

Примечания

  • Я не рекомендую функции префикса с get в Swift. Это нарушит определенные виды совместимости с ObjC.
  • Я рекомендую развернуть весь путь до объекта Book, прежде чем возвращать результаты в качестве Future. Существует несколько способов, с помощью которых эта система может выйти из строя, и гораздо удобнее, если вы проверите все эти вещи, прежде чем обернуть их в Future. Переход к [Book] намного лучше для остальной части вашего кода Swift, чем передача NSArray.
10
ответ дан Community 5 September 2018 в 08:29
поделиться
self.urlSession.dataTask(with: request, completionHandler: { (data, response, error) in
            self.endNetworkActivity()

            var responseError: Error? = error
            // handle http response status
            if let httpResponse = response as? HTTPURLResponse {

                if httpResponse.statusCode > 299 , httpResponse.statusCode != 422  {
                    responseError = NSError.errorForHTTPStatus(httpResponse.statusCode)
                }
            }

            var apiResponse: Response
            if let _ = responseError {
                apiResponse = Response(request, response as? HTTPURLResponse, responseError!)
                self.logError(apiResponse.error!, request: request)

                // Handle if access token is invalid
                if let nsError: NSError = responseError as NSError? , nsError.code == 401 {
                    DispatchQueue.main.async {
                        apiResponse = Response(request, response as? HTTPURLResponse, data!)
                        let message = apiResponse.message()
                        // Unautorized access
                        // User logout
                        return
                    }
                }
                else if let nsError: NSError = responseError as NSError? , nsError.code == 503 {
                    DispatchQueue.main.async {
                        apiResponse = Response(request, response as? HTTPURLResponse, data!)
                        let message = apiResponse.message()
                        // Down time
                        // Server is currently down due to some maintenance
                        return
                    }
                }

            } else {
                apiResponse = Response(request, response as? HTTPURLResponse, data!)
                self.logResponse(data!, forRequest: request)
            }

            self.removeRequestedURL(request.url!)

            DispatchQueue.main.async(execute: { () -> Void in
                completionHandler(apiResponse)
            })
        }).resume()
0
ответ дан CrazyPro007 5 September 2018 в 08:29
поделиться

Другой пример:

class func getExchangeRate(#baseCurrency: String, foreignCurrency:String, completion: ((result:Double?) -> Void)!){
    let baseURL = kAPIEndPoint
    let query = String(baseCurrency)+"_"+String(foreignCurrency)

    var finalExchangeRate = 0.0
    if let url = NSURL(string: baseURL + query) {
        NSURLSession.sharedSession().dataTaskWithURL(url) { data, response, error in

            if ((data) != nil) {
                let jsonDictionary:NSDictionary = NSJSONSerialization.JSONObjectWithData(data!, options: nil, error: nil) as NSDictionary

                if let results = jsonDictionary["results"] as? NSDictionary{
                    if let queryResults = results[query] as? NSDictionary{
                        if let exchangeRate = queryResults["val"] as? Double{
                            let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
                            dispatch_async(dispatch_get_global_queue(priority, 0)) {
                                dispatch_async(dispatch_get_main_queue()) {
                                    completion(result: exchangeRate)
                                }
                            }

                        }
                    }
                }
            }
            else {
                completion(result: nil)
            }

        }.resume()
    }
}    

Вызов:

 Currency.getExchangeRate(baseCurrency: "USD", foreignCurrency: "EUR") { (result) -> Void in
                if let exchangeValue = result {
                    print(exchangeValue)
                }
            }
8
ответ дан ericgu 5 September 2018 в 08:29
поделиться

Swift 4.0

Для async Request-Response вы можете выполнить обработчик завершения пользователем. См. Ниже, я изменил ваше решение с помощью парадигмы обработки завершения.

func getGenres(_ completion: @escaping (NSArray) -> ()) {

        let urlPath = "http://creative.coventry.ac.uk/~bookshop/v1.1/index.php/genre/list"
        print(urlPath)

        guard let url = URL(string: urlPath) else { return }

        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard let data = data else { return }
            do {
                if let jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary {
                    let results = jsonResult["genres"] as! NSArray
                    print(results)
                    completion(results)
                }
            } catch {
                //Catch Error here...
            }
        }
        task.resume()
    }

Вы можете вызвать эту функцию, как показано ниже. Простой

getGenres { (array) in
    // Do operation with your array
}
1
ответ дан Jaydeep 5 September 2018 в 08:29
поделиться

Свифт 3 версии ответа @Alexey Globchastyy:

class func getGenres(completionHandler: @escaping (genres: NSArray) -> ()) {
...
let task = session.dataTask(with:url) {
    data, response, error in
    ...
    resultsArray = results
    completionHandler(genres: resultsArray)
}
...
task.resume()
}
3
ответ дан Nebojsa Nadj 5 September 2018 в 08:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: