web-dev-qa-db-fra.com

Exception de lancement UIWebView pour [WebActionDisablingCALayerDelegate setBeingRemoved:]

Lors de l'exécution contre iOS 8, j'ai commencé à voir l'exception suivante provenant des entrailles profondes de UIWebView:

[WebActionDisablingCALayerDelegate setBeingRemoved:]: sélecteur non reconnu envoyé à l'instance 0x167ee900

* WebKit a supprimé une exception non interceptée dans le webView: willRemoveScrollingLayer: withContentsLayer: forNode: delegate: - [WebActionDisablingCALayerDelegate setBeingRemoved:

Cela se produit lorsque je modifie certaines contraintes sur mon UIWebView et que j'appelle ensuite:

 self.webViewWidthConstraints.constant = newWidth;
 [self.webView setNeedsLayout];
 [self.webView layoutIfNeeded];

(C'est pour que le contenu de la vue Web soit restitué pour s'adapter correctement à sa largeur).

Heureusement, l'exception est rejetée, donc l'application ne plante pas. Pourquoi cela se produit-il et existe-t-il un moyen de l'empêcher?

43
Arie Litovsky

J'ai trouvé cela en ajoutant "-webkit-transform: translateZ (0px);" au contenu défilant (j'ai une div à l'intérieur de mon conteneur défilable), cela a résolu le problème pour moi. J'espère que cela t'aides.

12
maidbarion

Je ne sais pas si c'est votre cas, mais j'ai également commencé à voir ce problème sur iOS 8 et nous l'avons identifié jusqu'à l'utilisation de la propriété CSS suivante sur un iframe:

-webkit-overflow-scrolling: touch;

Après l'avoir supprimé, nous n'avions plus ces messages d'erreur.

Remarque: dans mon cas, cela ne s'est pas produit en réponse à la modification de contraintes, mais plutôt lors de la navigation dans le HTML.

9
André Morujão

Comme aucune des réponses fournies ne pouvait m'aider, j'ai dû résoudre ce problème à l'aide de l'exécution d'Objective-C.

J'ai d'abord fourni une fonction simple:

id setBeingRemoved(id self, SEL selector, ...)
{
   return nil;
}

Ensuite, ces deux lignes:

    Class class = NSClassFromString(@"WebActionDisablingCALayerDelegate");
    class_addMethod(class, @selector(setBeingRemoved:), setBeingRemoved, NULL);

Et il fonctionne.

7
Andrey Chernukha

Utilisez WKWebView au lieu de UIWebView . (il a d'abord été inclus dans iOS 8). Je l'ai essayé et il semble qu'il n'ait pas ce bug. En outre, il peut améliorer les performances par rapport à son prédécesseur. Semble probable que Apple fera la norme de facto dans un avenir proche, sinon maintenant. Il a des interfaces et des délégués quelque peu similaires à UIWebView. Cela vaut vraiment la peine d'essayer.

Si vous ciblez une version antérieure à iOS 8, vous pouvez implémenter des procédures de secours pour charger UIWebView ou WKWebView, vous êtes ici une implémentation prête à l'emploi

4
webo80

Dans mon cas, le problème était une <table> à l'intérieur du contenu iframe. La largeur de la table était supérieure à la largeur de l'iframe définie via CSS. Le défilement iframe était désactivé et le tableau a étiré l'iframe à la largeur minimale calculée du tableau. Autre effet secondaire: le contenu de l'iframe n'était pas complètement visible (coupé sur le côté droit).

|--- Available viewport width -------------|
|--- defined and estimated iframe width ---|
|--- table width in the iframe content > than defined iframe width ---|
|--- iframe stretched to the calculated table width ------------------|

La suppression du contenu du tableau iframe sous forme de table a résolu le problème.

0
medium8

Comme @ André Morujão a répondu, en supprimant -webkit-overflow-scrolling:touch; de l'élément de défilement arrête l'exception. Mais j'ai constaté que l'exception ne se produisait que lorsque j'ai ajouté display:none css à l'élément de défilement.

Modifier: j'ai pu continuer à utiliser display:none pour masquer mon élément de défilement en mettant -webkit-overflow-scrolling:touch; à l'intérieur de sa propre classe .scroll et en utilisant jquery pour ajouter et supprimer cette classe de mon élément de défilement avant et après l'avoir masqué:

<style>
    .scroll
    {
         -webkit-overflow-scrolling:touch;
    }
</style>
<script>
function hide()
{
    $('#scrolling_element).removeClass('scroll');
    $('#scrolling_element).css('display', 'none');
}
function show()
{
    $('#scrolling_element).css('display', 'block');
    $('#scrolling_element).addClass('scroll');
}
</script>
0
Mark