Сохранение значений в завершении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 значение при попытке вызвать словарь.

Короче говоря, мой вопрос в том, как я могу присвоить значения обработчику завершения, и может быть вызван в другом месте в проекте Xcode?

Ваш вопрос искажен. Ваш примерный код недействителен и не отображает обработчик завершения.

Я подозреваю, что вы неправильно поняли, как работают асинхронные запросы и обработчики завершения. Вот последовательность.

  1. Вызвать функцию и предоставить обработчик завершения
  2. Функция возвращает немедленно, и в то время в будущих существах, выполняющих запрос
  3. Следующая строка после завершения обработчика запуска до запроса даже начала обработку. Приложение продолжает работать. Нет результата, потому что запрос еще не завершен.
  4. Асинхронный запрос завершается. Оригинальный метод вызывает обработчик завершения. СЕЙЧАС результат доступен в коде обработчика завершения. Код обработчика завершения делает все, что необходимо для обработки результатов.

Вот реалистичный пример того, как может работать 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 запускается дальше, но изображение все еще не загружено. На этом этапе невозможно вернуть результат, потому что загрузка изображения еще не началась.

  • Как создать вертикальное меню прокрутки в spritekit?
  • Преобразование двухбайтового массива UInt8 в UInt16 в Swift
  • Как я могу справиться с дефолтом вывода @objc с помощью #selector () в Swift 4?
  • Как создать методы classа, соответствующие протоколу, совместно используемому Swift и Objective-C?
  • Как импортировать файл Swift из другого файла Swift?
  • Правильно Разбор JSON в Swift 3
  • Невозможно преобразовать значение типа «Meme!» к ожидаемому типу аргументов '@noescape (Meme) throws -> Bool'
  • Кнопка Swift Spritekit Adding программно
  • Есть ли способ установить связанные объекты в Swift?
  • Что такое Swift-эквивалент ответаSoSelector?
  • Получить имя classа объекта как строку в Swift
  • Давайте будем гением компьютера.