Подтвердить что ты не робот

Невоспроизводимые сбои в работе веб-камеры

У меня есть iPad-приложение, которое в App Store уже около трех месяцев, и я получаю некоторые странные отчеты о сбоях, которые я не могу понять. Это не так часто, с момента запуска запускалось около 15-20 экземпляров, но до сих пор достаточно частым, чтобы на самом деле обмануть меня. Сбои немного отличаются (см. Следы стека ниже), но поскольку они связаны с WebCore, я предполагаю, что они связаны с использованием UIWebView в приложении и могут иметь общую причину, хотя я не на 100% положительный. Цель развертывания приложения - iOS 6.0, но сбои появляются на iPad 2, iPad 3 и iPad Mini, исключительно на iOS 7.

В приложении есть только одно место, где я использую webview, для отображения веб-страниц новостей из разных источников. У меня есть один контроллер представления для этого, который имеет UIWebView как его вид. Существует один экземпляр этого контроллера представления, который живет во всем приложении, каждый раз, когда выбирается новая статья, существующий веб-просмотр перезагружается с URL-адресом недавно выбранной статьи.

Одно из предлагаемых решений, основанных на обсуждении проблем WebCore, предложило установить свойство webviews delegate в nil в методе контроллера dealloc. К сожалению, я не думаю, что это применимо в моем случае, потому что контроллер просмотра не освобождается в течение жизненного цикла приложения.
Другой проблемой могут быть неправильные веб-страницы с плохими ссылками на изображение в CSS (loadPendingImages crash). Однако я не мог найти такую ​​страницу.
Кроме того, я дважды проверял и выполнял операции, связанные с веб-просмотром, в основном потоке.

Аварии

Exception Type: EXC_BAD_ACCESS 
Code: KERN_INVALID_ADDRESS

со следующими трассировками стека (полный здесь)

0 WebCore WebCore::StyleResolver::applyMatchedProperties(WebCore::StyleResolver::MatchResult const&, WebCore::Element const*) + 815
1 WebCore WebCore::StyleResolver::applyMatchedProperties(WebCore::StyleResolver::MatchResult const&, WebCore::Element const*) + 788
2 WebCore WebCore::StyleResolver::styleForElement(WebCore::Element*, WebCore::RenderStyle*, WebCore::StyleSharingBehavior, WebCore::RuleMatchingBehavior, WebCore::RenderRegion*) + 948
3 WebCore WebCore::Document::styleForElementIgnoringPendingStylesheets(WebCore::Element*) + 96
4 WebCore WebCore::Element::computedStyle(WebCore::PseudoId) + 142
5 WebCore WebCore::ComputedStyleExtractor::propertyValue(WebCore::CSSPropertyID, WebCore::EUpdateLayout) const + 458

и

0 WebCore WebCore::StyleResolver::loadPendingImages() + 1153
1 WebCore WebCore::ResourceRequestBase::~ResourceRequestBase() + 104
2 WebCore WebCore::StyleResolver::applyMatchedProperties(WebCore::StyleResolver::MatchResult const&, WebCore::Element const*) + 782
3 WebCore WebCore::StyleResolver::styleForElement(WebCore::Element*, WebCore::RenderStyle*, WebCore::StyleSharingBehavior, WebCore::RuleMatchingBehavior, WebCore::RenderRegion*) + 948
4 WebCore WebCore::Document::styleForElementIgnoringPendingStylesheets(WebCore::Element*) + 96
5 WebCore WebCore::Element::computedStyle(WebCore::PseudoId) + 142

и

0 WebCore WebCore::StyleResolver::adjustRenderStyle(WebCore::RenderStyle*, WebCore::RenderStyle*, WebCore::Element*) + 19
1 WebCore WebCore::StyleResolver::styleForElement(WebCore::Element*, WebCore::RenderStyle*, WebCore::StyleSharingBehavior, WebCore::RuleMatchingBehavior, WebCore::RenderRegion*) + 964
2 WebCore WebCore::Document::styleForElementIgnoringPendingStylesheets(WebCore::Element*) + 96
3 WebCore WebCore::Element::computedStyle(WebCore::PseudoId) + 142
4 WebCore WebCore::ComputedStyleExtractor::propertyValue(WebCore::CSSPropertyID, WebCore::EUpdateLayout) const + 458
5 WebCore WebCore::CSSComputedStyleDeclaration::getPropertyValue(WebCore::CSSPropertyID) const + 42

и

0 WebCore WebCore::TimerBase::heapDeleteMin() + 37
1 WebCore WebCore::ThreadTimers::sharedTimerFiredInternal() + 94
2 WebCore WebCore::ThreadTimers::sharedTimerFiredInternal() + 94
3 WebCore WebCore::timerFired(__CFRunLoopTimer*, void*) + 24
4 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 14
5 CoreFoundation __CFRunLoopDoTimer + 782

Кто-нибудь испытал подобные аварии? Если да:
1. Есть ли способы их тиражирования?
2. Как можно отлаживать их без их тиражирования?
3. Какие исправления решают проблемы?

Спасибо!

4b9b3361

Ответ 1

У меня была такая же проблема в приложении, над которым я работал, это странно произошло только на более старых устройствах под управлением iOS 7. Я подозреваю, что это связано с тем, что они не могут идти в ногу.

То, что у меня было, было UITableView, где одна из строк открывала бы UIViewController, у которой UIWebView на нем для пользовательских объявлений. То, что я нашел, это то, что на старых устройствах объекты и память, где они были свободны гораздо чаще, чем я видел на других платформах. Я мог очень легко подражать краху на iPhone 4, введя/выйдя из экрана 2 или 3 раза. Где в качестве iPhone 5 я потратил 15 минут на то, чтобы сделать то же самое, и не мог его винить.

Я знаю, что вы можете почувствовать, что ваш контроллер не освобожден, но действительно звучит так, как если бы он был, или какая-либо ссылка была удалена. Я также видел, что мои ссылки делегатов несколько раз исчезают и в этом приложении.

Мой совет и то, что сработало для меня, - это остановить выполнение webview и установить все на nil, когда сможете.

В одном экземпляре моего приложения я решил сделать это в обратном вызове viewWillDisappear, потому что в моих обстоятельствах он исчез из пользователя и воссоздан позже, поэтому я все это сделал так:

[webView stopLoading];

self.webView.delegate = nil;
self.webView = nil;

Ответ 2

Посмотрите на свой код Javascript-to- Objective-C, и если вы выполняете/вызываете код javascript, убедитесь, что script не вызывает новые вызовы Objective-C.

Это правильное использование:

Javascript >> Objective-C

Objective-C >> Javascript

Это причина сбоя:

Objective-C >> Javascript >> Objective-C (здесь возможен сбой в зависимости от условий гонки)

Решение специфично для вашего кода проекта. Но проще всего обернуть весь Javascript в setTimeout(), чтобы запланировать выполнение в потоке Javascript. Вот простой пример: ваш код Objective-C должен выполнить этот script:

storeUserPhoneNumber("011 123 4567");

Сбой произойдет, если функция storeUserPhoneNumber вернется к Objective-C коду (прямо или косвенно) в своем теле. Чтобы исправить это, просто оберните код в setTimeout следующим образом:

setTimeout(function() {
    storeUserPhoneNumber("011 123 4567");
}, 0);