Запрос AlamoFire GET api не работает должным образом

Я пытаюсь узнать, как использовать AlamoFire, и у меня возникают проблемы.

Мой метод до сих пор выглядит следующим образом:

func siteInfo()->String?{
    var info:NSDictionary!
    var str:String!
    Alamofire.request(.GET, MY_API_END_POINT).responseJSON {(request, response, JSON, error) in
        info = JSON as NSDictionary
        str = info["access_key"] as String
        //return str
    }
    return str
}

Это возвращает значение nil, которое является проблемой. Из того, что я прочитал здесь, это связано с тем, что запрос может занять некоторое время, поэтому закрытие не выполняется до момента возврата. Предлагаемое решение о переносе возврата в закрытие не работает для меня, и компилятор просто кричит (добавление ->String после (request,response,JSON,error), которое дает "String", не является подтипом void "). То же самое касается другого решения.

Любые идеи? Даже некоторый исходный код, не связанный с этой проблемой, который использует AlamoFire, был бы полезен.

Спасибо!

Ответы

Ответ 1

Один из способов справиться с этим - передать закрытие (я обычно называю его completionHandler) вашей функцией siteInfo и вызвать это внутри Alamofire.request закрытия:

func siteInfo(completionHandler: (String?, NSError?) -> ()) -> () {
    Alamofire.request(.GET, MY_API_END_POINT).responseJSON {
        (request, response, JSON, error) in

        let info = JSON as? NSDictionary // info will be nil if it not an NSDictionary
        let str = info?["access_key"] as? String // str will be nil if info is nil or the value for "access_key" is not a String

        completionHandler(str, error)
    }
}

Затем вызовите его так (не забудьте обработать ошибку):

siteInfo { (str, error) in
    if str != nil {
        // Use str value
    } else {
        // Handle error / nil value
    }
}

В комментариях, которые вы задали:

Итак, как бы вы сохранили информацию, которую вы собираете, из запроса на получение, если вы может делать только вещи внутри закрытия и не воздействовать на объекты за пределами закрытие? Кроме того, как отслеживать, когда запрос имеет закончили?

Вы можете сохранить результат запроса get к переменной экземпляра в своем классе изнутри закрытия; нет ничего о закрытии, препятствующем вам сделать это. То, что вы делаете оттуда, действительно зависит от того, что вы хотите делать с этими данными.

Как насчет примера?

Поскольку похоже, что вы получаете форму ключа доступа, которая получает запрос, возможно, вам это нужно для будущих запросов, сделанных в других функциях.

В этом случае вы можете сделать что-то вроде этого:

Примечание. Асинхронное программирование - это огромная тема; слишком много, чтобы покрыть здесь. Это всего лишь один пример того, как вы можете обрабатывать данные, возвращаемые с вашего асинхронного запроса.

public class Site {
    private var _accessKey: String?

    private func getAccessKey(completionHandler: (String?, NSError?) -> ()) -> () {

        // If we already have an access key, call the completion handler with it immediately
        if let accessKey = self._accessKey {
            completionHandler(accessKey, nil)
        } else { // Otherwise request one
            Alamofire.request(.GET, MY_API_END_POINT).responseJSON {
                (request, response, JSON, error) in

                let info = JSON as? NSDictionary // info will be nil if it not an NSDictionary
                let accessKey = info?["access_key"] as? String // accessKey will be nil if info is nil or the value for "access_key" is not a String

                self._accessKey = accessKey
                completionHandler(accessKey, error)
            }
        }
    }

    public func somethingNeedingAccessKey() {
        getAccessKey { (accessKey, error) in
            if accessKey != nil {
                // Use accessKey however you'd like here
                println(accessKey)
            } else {
                // Handle error / nil accessKey here
            }
        }
    }
}

С этой настройкой вызов somethingNeedingAccessKey() в первый раз вызовет запрос на получение ключа доступа. Любые вызовы somethingNeedingAccessKey() после этого будут использовать значение, уже сохраненное в self._accessKey. Если вы выполняете оставшуюся часть somethingNeedingAccessKey, работающей в закрытии, передается в getAccessKey, вы можете быть уверены, что ваш accessKey всегда будет действительным. Если вам нужна другая функция, которая нуждается в accessKey, просто напишите ее так же, как написано somethingNeedingAccessKey.

public func somethingElse() {
    getAccessKey { (accessKey, error) in
        if accessKey != nil {
            // Do something else with accessKey
        } else {
            // Handle nil accessKey / error here
        }
    }
}