34 votes

Comment puis-je savoir lorsqu'un rendu UIWebView est terminé (pas de chargement)?

Je sais quand son chargement est terminé ... (webViewDidFinishLoad), mais je veux utiliser

 [webView.layer renderInContext:UIGraphicsGetCurrentContext()];
 

créer une image à partir de UIWebView. Parfois, je reçois l'image avant que WebView termine son rendu. Je peux utiliser performSelector pour retarder l'obtention de l'image, mais le temps d'attente est arbitraire et fragile.

4voto

Sean Reilly Points 545

Cela peut dépendre du type de contexte graphique dans lequel la vue doit être rendue, mais vous pouvez appeler

 - (void)drawRect:(CGRect)area forViewPrintFormatter:(UIViewPrintFormatter *)formatter
 

ce qui incite apparemment UIWebView à penser qu'il est en cours d'impression. Cela peut aider si votre objectif ultime est de capturer la page complète. Nous avons récemment eu le problème suivant: même si la page était entièrement chargée, l'appel de plain -drawRect: plain ne rendait pas la page entière si une partie était hors écran.

2voto

ASP Points 108


Pourquoi ne pas utiliser l’événement window.onload ou jQuerys $ (document) .ready pour déclencher le rappel shouldStartLoad?

Quelque chose comme:

 $(document).ready(function(){
    location.href = "app://do.something"
})
 

et dans votre UIWebViewDelegate faire quelque chose comme:

 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSURL *url = request.URL;

    if([url.host isEqualToString:@"app"]){
        //maybe check for "do.something"
        //at this point you know, when the DOM is finished
    }
}
 

Avec cette méthode, vous pouvez transférer tous les événements possibles du code JS vers votre code obj-c.

J'espère que ça t'as aidé. L'échantillon de code est écrit dans le navigateur et n'est donc pas testé! ;-)

2voto

Dan Points 16670

J'ai eu un problème similaire dans une application où je suis entièrement d'en contrôler le contenu. Cela ne fonctionnera pas si vous chargez arbitraire des pages du web, mais il peut fonctionner si vous savez que votre haut niveau DOM structure et qu'il n'a pas beaucoup de changement.

Ce qui a fonctionné pour moi a été la suivante.

J'ai eu récursive de trouver le premier UIWebView's sous-vue de type UIWebOverflowScrollView avec un cadre de (0, 0, 1024, 768). Si je ne pouvais pas en trouver un, c'était un signe sûr que le contenu n'a pas été rendue encore. L'ayant trouvé, je vérifie ce point de vue de l' layer.sublayers.count. Lorsque le rendu des finitions, je finis toujours avec un ou trois sous-couches. Si le rendu n'est pas fini, cependant, l'affichage du contenu toujours eu tout au plus une sous-couche.

Maintenant, c'est spécifique à mon DOM structure-mais il se peut que vous faire un semblable "test" si vous comparez la sous-couche de l'arbre avant et après le rendu. Pour moi, la règle de base était "le premier de manière récursive trouvés sous-vue de type UIWebOverflowScrollView ont au moins trois sous-couches", pour vous, il sera probablement différente.

De toute façon, prendre le plus grand soin si vous décidez d'utiliser cette approche, même si vous n'aurez pas rejeté en UIWebView's de la vue et de la couche de la hiérarchie, ce genre de comportement n'est pas fiable et est très susceptible de changer dans les futures versions d'iOS. Il peut très bien être incompatibles entre iOS 5 et iOS 6.

Enfin, des extraits de code pour MonoTouch qui devrait être simple à traduire pour Objectif C:

bool IsContentScrollView (UIScrollView scrollView)
{
    return scrollView.Frame.Equals (new RectangleF (0, 0, 1024, 768));
}

[DllImport ("/usr/lib/libobjc.dylib")]
private static extern IntPtr object_getClassName (IntPtr obj);

public static string GetClassName (this UIView view) {
    return Marshal.PtrToStringAuto (object_getClassName (view.Handle));
}
bool IsWebOverflowScrollView (UIScrollView scrollView)
{
    return scrollView.GetClassName () == "UIWebOverflowScrollView";
}

IEnumerable<UIScrollView> ScrollViewsInside (UIView view)
{
    foreach (var subview in view.Subviews) {
        foreach (var scrollView in ScrollViewsInside (subview).ToList())
            yield return scrollView;

        if (subview is UIScrollView)
            yield return (UIScrollView)subview;
    }
}

bool CanMakeThumbnail {
    get {
        var scrollViews = ScrollViewsInside (this).Where (IsWebOverflowScrollView).ToList ();
        var contentView = scrollViews.FirstOrDefault (IsContentScrollView);

        // I don't know why, but this seems to be a good enough heuristic.
        // When the screen is black, either contentView is null or it has just 1 sublayer.

        // This may *break* on any iOS updates or DOM changes--be extra careful!

        if (contentView == null)
            return false;

        var contentLayer = contentView.Layer;
        if (contentLayer == null || contentLayer.Sublayers == null || contentLayer.Sublayers.Length < 3)
            return false;

        return true;
    }
}

-2voto

Cool Points 7

Si vous avez accès au fichier HTML et que vous pouvez le modifier, ajoutez simplement une variable spéciale qui indiquera au code que le rendu est effectué.
Ensuite, utilisez la méthode stringByEvaluatingJavaScriptFromString pour savoir si vous démarrez certaines actions ou non.
L'exemple ci-dessous est assez sale, mais espérons que cela vous aidera et vous donnera l'idée:

 (void)webViewDidFinishLoad:(UIWebView *)webView
{
    BOOL renderingDone = NO;
    while (!(renderingDone == [[webView stringByEvaluatingJavaScriptFromString:@"yourjavascriptvariable"] isEqualToString:@"YES"]))
    {
        // the app will be "freezed" till the moment when your javascript variable will not get "YES" value 
    }
    // do your stuff, rendering is done 
}
 

-4voto

 if (webView.loading == YES)
        {
            //Load image
        }
 

Quelque chose comme ça pourrait marcher.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X