Сохранение значений в завершенииHandlers – Swift
Я создаю completionHandler
который возвращает словарь, но когда я вызываю этот метод в другом classе, значение его равно nil.
func fetchLatestPosts(completionHandler: (responseDict: NSDictionary) -> Void in { // Bunch of JSON Parsing for dictionary to be completed var theDictionary = JSON Dictionary value responseDict = theDictionary as NSDictionary }
Затем я fetchLatestPost
вызвать его в другом classе, так что значение, fetchLatestPost
может быть просмотрено fetchLatestPost
Dictionary, и данные, представленные на основе этого. Например,
func parseDictionary() { NetworkManager.sharedInstance.fetchLatestPosts(responseDict: NSDictionary) if (responseDict != nil) { println("Dictionary is not empty") }
Проблема здесь в том, что когда я fetchLatestPosts
функцию fetchLatestPosts
я получаю nil
значение при попытке вызвать словарь.
- «Classname не имеет имени участника» при добавлении цели UIButton
- Swift: #warning эквивалент
- Печать символа Unicode из переменной (swift)
- Как использовать метод экземпляра как обратный вызов для функции, которая принимает только func или буквальное закрытие
- Как разрешить «неоднозначное использование» ошибки компиляции с синтаксисом Swift #selector?
Короче говоря, мой вопрос в том, как я могу присвоить значения обработчику завершения, и может быть вызван в другом месте в проекте Xcode?
- Оператор равенства Swift для вложенных массивов
- NSDate вчера
- Как преобразовать массив байтов в шестнадцатеричную строку в Swift
- @selector () в Swift?
- metadata.downloadURL () больше не распознается?
- Как избежать принудительной разворачивания переменной?
- iOS: конвертировать UTC NSDate в локальный часовой пояс
- Swift - Как преобразовать String в Double
Ваш вопрос искажен. Ваш примерный код недействителен и не отображает обработчик завершения.
Я подозреваю, что вы неправильно поняли, как работают асинхронные запросы и обработчики завершения. Вот последовательность.
- Вызвать функцию и предоставить обработчик завершения
- Функция возвращает немедленно, и в то время в будущих существах, выполняющих запрос
- Следующая строка после завершения обработчика запуска до запроса даже начала обработку. Приложение продолжает работать. Нет результата, потому что запрос еще не завершен.
- Асинхронный запрос завершается. Оригинальный метод вызывает обработчик завершения. СЕЙЧАС результат доступен в коде обработчика завершения. Код обработчика завершения делает все, что необходимо для обработки результатов.
Вот реалистичный пример того, как может работать asynchronous процесс с обработчиками завершения: (Вы можете найти рабочий проект Xcode, который демонстрирует этот код в Github по этой ссылке )
Сначала class AsyncManager, который имитирует загрузку изображения из Интернета:
class AsyncManager { static let sharedAsyncManager = AsyncManager() func asyncFetchImage(#imageName: String, completion: (image: UIImage?, status: String) -> ()) { println("Entering \(__FUNCTION__)") //Simulate a network operation by waiting 3 seconds before loading an image let nSecDispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(3.0 * Double(NSEC_PER_SEC))) let queue = dispatch_get_main_queue() dispatch_after(nSecDispatchTime, queue) { () -> Void in let result = UIImage(named: imageName) println("Loading image in background") let status = result != nil ? "image loaded" : "Error loading image" println("About to call completion handler") completion(image: result, status: status) } println("Leaving \(__FUNCTION__)") } }
Это синглтон. Он имеет статический let sharedAsyncManager, который вы используете для извлечения одного экземпляра AsyncManager.
AsyncManager предоставляет один метод asyncFetchImage, который принимает имя изображения и блок завершения. Функция не возвращает никакого результата, потому что она немедленно возвращается, прежде чем произойдет загрузка изображения.
Код действительно не загружает изображение из Интернета. Вместо этого он просто запускает вызов GCD dispatch_after, чтобы подождать 3 секунды перед загрузкой изображения и вызовом блока завершения.
Теперь я создаю class ViewController и даю ему кнопку «Загрузить изображение». Я создаю IBOutlet
theImageView
для UIImageView
, который отобразит изображение, которое я собираюсь загрузить.
Я пишу метод IBAction для кнопки Load Image. Вот что такое IBAction выглядит так:
@IBAction func loadImage(sender: UIButton) { let theAsyncManager = AsyncManager.sharedAsyncManager println("about to call asyncFetchImage") theAsyncManager.asyncFetchImage(imageName: "wareto_blue_150x115") { (image, status) -> () in println("Beginning completion block") self.theImageView.image = image println("In completion block, status = \(status)") } println("After call to asyncFetchImage") } }
Теперь самое интересное. Вот последовательность событий:
Я нажимаю кнопку loadImage. Выполняется метод IBAction.
Он получает ссылку на диспетчер загрузки async singleton.
Он отображает сообщение, затем вызывает theAsyncManager.asyncFetchImage. Метод AsyncManager.asyncFetchImage отображает сообщение на входе, очереди на вызов для загрузки изображения через 3 секунды, отображает сообщение «оставить» и возвращается до загрузки изображения . Нечего возвращать, потому что код загрузки изображения еще не запущен.
В режиме loadImage controllerа View отображается сообщение «После вызова asyncFetchImage» и возвращается.
Через несколько секунд код внутри asyncFetchImage запускается. Он отображает сообщение, загружает изображение, а затем вызывает обработчик завершения.
Вот набор сообщений, которые вы возвращаете, когда запускаете приведенный выше код:
about to call asyncFetchImage Entering asyncFetchImage(imageName:completion:) Leaving asyncFetchImage(imageName:completion:) After call to asyncFetchImage Loading image in background About to call completion handler Beginning completion block In completion block, status = image loaded
Обратите внимание, что последняя строка loadImage IBAction:
println("After call to asyncFetchImage")
отображает сообщение до появления сообщения о загрузке изображения. Вызов кода для asyncFetchImage немедленно возвращается, прежде чем будет выполнена какая-либо работа. Код после вызова asyncFetchImage запускается дальше, но изображение все еще не загружено. На этом этапе невозможно вернуть результат, потому что загрузка изображения еще не началась.