Swift: Проблем с нишката с DismissViewController() и отхвърляне на клавиатурата

Изпращам някои данни до сървъра си и при отговор отхвърлям своя контролер за изглед. В viewWillDisappear() на viewController се опитвам да отхвърля клавиатурата.

Ако presentER viewController не е основният изглед контролер, получавам изключението „[UIKeyboardTaskQueue waitUntilAllTasksAreFinished] може да се извиква само от основната нишка.'“. Опитах се да извикам функция, която отхвърли клавиатурата, след това viewcontroller (премахвайки необходимостта от viewwilldisappear()), но има същия проблем.

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

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

Код: //в рамките на presentER viewcontroller

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; когато работите с UI, обикновено много актуализации ще се случват асинхронно и затова аз лично считам това за лоша практика. - 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 нишка. В този блок за завършване правите UI код. Щетите вече са нанесени и кодът, който публикувате, не е източникът на проблема. използвайте извикване към NSThread.isMainThread() all във всичките си блокове/манипулатори за завършване, за да видите кой код се изпълнява в основната нишка и кой не. - person Duncan C; 24.06.2015
comment
Проследих проблема. Случаят е различен, отколкото се смяташе по-рано. Това се случва, когато се опитвам да покажа UIAlertController (чрез presentViewController), защото заявката не върна правилни данни/идентификационни данни. run_on_main_thread { if let controller = visibleViewController() //recursive { controller.view.endEditing(true) controller.presentViewController(alert, animated: true, completion: 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