Swift: проблема с потоками с DismissViewController() и отключением клавиатуры

Я отправляю некоторые данные на свой сервер, и после ответа я отключаю свой контроллер представления. В viewController viewWillDisappear() я пытаюсь отключить клавиатуру.

Если presentER viewController не является корневым контроллером представления, я получаю исключение «[UIKeyboardTaskQueue waitUntilAllTasksAreFinished] может вызываться только из основного потока». Я попытался вызвать функцию, которая отключала клавиатуру, а затем контроллер представления (удаляя необходимость в viewwilldisappear()), но у нее та же проблема.

Код: // в представленном контроллере представления

override func viewWillDisappear(animated: Bool)
    {
            super.viewWillDisappear(animated)
            self.view.endEditing(true)
    }

Код: // внутри контроллера представления PresentER

func manage_response(//)
    {
            run_on_background_thread
            {
                    self.parse(//)
                    run_on_main_thread
                    {
                          self.presented_controller.dismissViewControllerAnimated(true, completion: nil)

                    }
            }
    }

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

Редактировать:

Синтаксис для функций завершающего метода, которые я использую для потоковой передачи:

func run_on_background_thread(code: () -> Void)
{
           dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), code)
}

func run_on_main_thread(code: () -> Void)
{
        dispatch_async(dispatch_get_main_queue(), code)
}

Решение:

Я отследил проблему. Дело обстоит иначе, чем предполагалось ранее. Это происходит, когда я пытаюсь отобразить UIAlertController (через presentViewController), потому что запрос не вернул правильные данные/учетные данные.

run_on_main_thread
            {
                    if let controller = visibleViewController() //recursive
                    {
                            controller.view.endEditing(true)
                            controller.presentViewController(alert, animated: true, completion: nil)
                    }
            }

person Ryan    schedule 24.06.2015    source источник
comment
Где определены run_on_background_thread и run_on_main_thread?   -  person Duncan C    schedule 24.06.2015
comment
Виноват. Они определены глобально в файле вспомогательных/вспомогательных функций. Включено сейчас. Примечание: они прекрасно работают во всем довольно сложном приложении, только когда клавиатуру нужно убрать, чтобы что-то пошло не так.   -  person Ryan    schedule 24.06.2015


Ответы (3)


Вы должны попытаться отклонить его в основной очереди следующим образом:

dispatch_async(dispatch_get_main_queue()) { self.presented_controller.dismissViewControllerAnimated(true, completion: nil) }

person Anand    schedule 24.06.2015
comment
Я делаю именно это, что дает мне исключение. - person Ryan; 24.06.2015
comment
Даже если вы используете вместо dispatch_async, dispatch_sync? - person Anand; 29.06.2015
comment
Есть много минусов с dispatch_sync; при работе с пользовательским интерфейсом, как правило, многие обновления будут происходить асинхронно, поэтому я лично считаю это плохой практикой. - person Ryan; 01.07.2015

У вас есть правильная общая идея, но то, что вы опубликовали, является псевдокодом. Дьявол кроется в деталях. Если вы получаете это сообщение об ошибке, значит, где-то ваш код выполняет вызовы UIKit из фонового потока.

NSThread имеет метод класса isMainThread(). Вы можете использовать это, чтобы проверить, какой код запускается в фоновом режиме.

person Duncan C    schedule 24.06.2015
comment
только аргументы manage_response() и parse() опущены. Я добавлю завершающие вызовы функций, которые я использую для run_on_main_thread и run_on_background_thread. - person Ryan; 24.06.2015
comment
Я предполагаю, что у вас где-то неправильное предположение. У вас есть блок завершения, который, по вашему мнению, выполняется в основном потоке, но это не так, он выполняется в потоке BG. В этом блоке завершения вы делаете код пользовательского интерфейса. Ущерб уже нанесен, и код, который вы публикуете, не является источником проблемы. используйте вызов NSThread.isMainThread() all во всех ваших блоках/обработчиках завершения, чтобы увидеть, какой код выполняется в основном потоке, а какой нет. - person Duncan C; 24.06.2015
comment
Я отследил проблему. Дело обстоит иначе, чем предполагалось ранее. Это происходит, когда я пытаюсь отобразить UIAlertController (через presentViewController), потому что запрос не вернул правильные данные/учетные данные. run_on_main_thread { if let controller = visibleViewController() // рекурсивный { controller.view.endEditing(true) controller.presentViewController(alert, анимированный: true, завершение: nil) } } - person Ryan; 26.06.2015
comment
Если вы решили свою проблему, вы должны опубликовать ответ на свой вопрос и принять его. - person Duncan C; 26.06.2015

Проблема заключалась в отображении UIAlertViewController. Эта логика/код решит такую ​​проблему:

run_on_main_thread
{
    if let controller = visibleViewController() //recursive
    {
         controller.view.endEditing(true)       
         controller.presentViewController(alert, animated: true, completion: nil)
    }
}
person Ryan    schedule 30.06.2015