Длительное нажатие приводит к ошибке/предупреждению, когда WKWebView пытается представить WKActionSheet

Моя иерархия представлений выглядит так:

  • (root) PRSBaseViewController - a UIViewController subclass - has child viewControllers
    • (presented) PRSModalWebViewController - a UINavigationController subclass
      • (pushed, animated:NO) PRSWebViewController - a UIViewController subclass - WKWebView is a subview.

Когда я пытаюсь и долго нажимаю на ссылку в WebView, я получаю сообщение об ошибке:

Warning: Attempt to present <WKActionSheet: 0x127520d10> on <PRSBaseViewController: 0x1275117f0> whose view is not in the window hierarchy!

Вместо представления навигации с помощью presentViewController:animated:completion и вместо этого используйте танец addChildViewController:, чтобы добавить его в контроллер представления в иерархию. Я не получаю ошибок, это довольно странно.

Кто-нибудь знает, что может быть причиной проблем с иерархией представлений?

Обновление: я составил суть всех моих занятий


person Shawn Throop    schedule 04.01.2015    source источник
comment
Возможно дубликат stackoverflow.com/questions/26460417/   -  person matt    schedule 05.01.2015
comment
@matt Я не пытаюсь скрыть общие листы, они подавляются против моей воли. Поведение, которого я не хочу и которое получаю, является ответом на его вопрос.   -  person Shawn Throop    schedule 05.01.2015
comment
В том-то и дело, что это частный класс Apple. Я разместил свою проблему на форумах разработчиков для хорошей меры. Спасибо, что взялись за дело.   -  person Shawn Throop    schedule 05.01.2015
comment
О, я вижу! Извини за это. Так что это то, что Apple выставляет в ответ на долгое нажатие. Я извиняюсь за то, что заставил вас просвещать меня, но я рад, что вы это сделали!   -  person matt    schedule 05.01.2015
comment
Так что же такое RootViewController? Вы говорите, что разместили Gist своих классов, но среди них нет RootViewController. Не могли бы вы показать, как RootViewController попадает в иерархию представлений и как он получает свое подпредставление WKWebView? (Он не может получить его в nib, так как в библиотеке объектов нет WKWebView; вы должны делать все это в коде.)   -  person matt    schedule 05.01.2015
comment
Очевидно, вы имеете в виду использовать PRSWebViewController в качестве контроллера корневого представления UINavigationController, но каким-то образом RootViewController прокрался в историю.   -  person matt    schedule 05.01.2015
comment
Извините, я использовал RootViewController в качестве замены для PRSBaseViewController до того, как я связал свой код, я думал, что это будет легче понять, мой плохой. Я обновил свой вопрос.   -  person Shawn Throop    schedule 05.01.2015
comment
Но сообщение об ошибке очень четко говорит, что это является RootViewController. Это моя точка зрения. Если вы ранее использовали RootViewController, я предполагаю, что у вас все еще есть старая версия раскадровки, лежащая в вашей промежуточной сборке. Я предлагаю вам начать с очистки кешей, как я объясню здесь: stackoverflow.com/a/6247073/341994   -  person matt    schedule 05.01.2015
comment
Плохо редактировал, исправил. RootViewController не существует, это был просто текст-заполнитель, чтобы было ясно, что это rootViewController окна делегата моего приложения.   -  person Shawn Throop    schedule 05.01.2015
comment
Эта ошибка возникает из-за того, что WebKit неправильно пытается представить WKActionSheet на [view.window rootViewController] (источник). Но если контроллер корневого представления уже что-то представляет, то это неправильно.   -  person Lily Ballard    schedule 07.05.2016


Ответы (2)


Я сталкивался с подобным поведением - и не понял, как и почему это происходит.

Вот мой обходной путь. Поскольку WKWebView вызывает мой RootViewController, я обрабатываю это, переопределяя PresentViewController RootViewController:animated:completion: - и если RootViewController уже имеет представленныйViewController, то он перенаправляет сообщение этому контроллеру. Кажется, это относится к предупреждающему сообщению и дает мне меню длительного нажатия при использовании WKWebView внутри модального представления.

- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {

    // Unsure why WKWebView calls this controller - instead of it's own parent controller
    if (self.presentedViewController) {
        [self.presentedViewController presentViewController:viewControllerToPresent animated:flag completion:completion];
    } else {
        [super presentViewController:viewControllerToPresent animated:flag completion:completion];
    }
}

Или быстро:

override func presentViewController(viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)?) {
    if presentedViewController != nil {
        // Unsure why WKWebView calls this controller - instead of it's own parent controller
        presentedViewController?.presentViewController(viewControllerToPresent, animated: flag, completion: completion)
    } else {
        super.presentViewController(viewControllerToPresent, animated: flag, completion: completion)
    }
}
person Todd    schedule 28.04.2015
comment
Это именно то, что я сделал, я просто забыл ответить на свой вопрос. - person Shawn Throop; 29.04.2015
comment
Итак, это исправление показывает список действий или подавляет его? Я хотел бы видеть список действий в своем приложении, чтобы я мог выполнить какое-либо действие - person Alix; 10.08.2015
comment
Это работает! Здорово! Добавьте код Тодда в свой контроллер, например ‹PRSBaseViewController›, в сведениях о предупреждении. - person Baryon Lee; 09.09.2015
comment
Это обходной путь, который я также реализовал. Эта проблема стала очевидной в моем приложении, когда я начал видеть отчеты о сбоях. Если WKWebView закрывается, а затем устройство поворачивается, проблема проявляется как исключение, и приложение аварийно завершает работу. - person isaac; 10.04.2016

Мы видели эту проблему и в PSPDFKit, и после изучения сборки UIKit и WKWebView исходников мы нашли обходной путь, который до сих пор не работает. ужасно, но не агрессивно.

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

https://gist.github.com/steipete/b00fc02aa9f1c66c11d0f996b1ba1265

И, пожалуйста, скопируйте rdar://26295020, чтобы это было исправлено вовремя для iOS 10. (Ошибка существует с iOS 8 и впервые появилась в iOS 8b5.)

person steipete    schedule 16.05.2016
comment
Это также работает с произвольной длинной цепочкой неизвестных представленных контроллеров представлений, которые нам нужны, потому что мы работаем над фреймворком, поэтому не нужно контролировать все контроллеры представлений в приложении. - person Douglas Hill; 16.05.2016