WebKit, préparation contenu local

iLandesiLandes Membre
novembre 2017 modifié dans API UIKit #1

Dans une application j'utilise WKWebView pour présenter des documents HTML relativement simple. Cela fonctionne correctement une fois que l'on a intégrer qu'on ne peut pas utilise WKWebView dans le storyboard directement. Je dis cela à  ceux qui voudrais s'y essayé, avec le WKWebView dans le storyboard on pert la rétro compatibilité.


 


Mon problème est que le temps de lancement d'une page web est relativement long. J'ai une collection View qui me permet de naviguer dans mes fichiers HTML. Franchement c'est très simple il n'y a pas plus de 4/5 fichiers qui peuvent être présentés et ceux-ci sont vraiment simple.


 


Je me demandais s'il était possible de précharger mes 4/5 fichiers HTML pour rendre mon application plus responsive. Les fichiers HTML sont intégrés à  mon Bundle.


 


D'avance merci de vos réponses et n'hésitez pas si vous avez besoin de précisions.


 


Je précise tout de même que mes fichiers .html contient un peu de CSS, une image et un background. Je ne peux donc pas passer par ce genre de code qui n'offre pas le rendu nécessaire.



do{
let html = try String(contentsOfFile: path, encoding: String.Encoding.utf8)
webView.loadHTMLString(html, baseURL: nil)
}catch{
print("Error!")
}

Seb


Mots clés:

Réponses

  • Luc-ALuc-A Membre
    novembre 2017 modifié #2

    Bonjour iLandes !


     


    Comment fais-tu pour charger tes documents HTML actuellement ?


    Si j'ai bien compris, tes documents HTML sont intégrés à  ton application mobile, et donc, tu n'as pas besoin d'une connexion Internet pour les charger.


    Dans ce cas, pourquoi ne pas faire comme ce que j'ai fait pour la carte, c'est-à -dire, créer une instance qui va charger tes documents avec l'appDelegate, et donc, avec l'application ? Comme ça, tes documents sont téléchargés directement.


     


    Regarde ici pour voir ce que j'ai fait avec la carte.


     


    As-tu essayé de charger tes documents sans l'image ? Je pose la question car c'est peut-être ça qui met du temps à  être chargé, surtout si l'image doit être redimensionnée par l'iPhone.


  • Pour charger, j'utilise ce code :



    func loadWebView(_ webView: WKWebView, fileName: String) {
    // Check File
    guard let path = Bundle.main.path(forResource: fileName,
    ofType: "html") else {
    print ("HTML File not found: \(fileName)")
    return
    }

    // Create request
    let url = URL(fileURLWithPath: path)
    let request = URLRequest(url: url)

    // Load Page
    webView.load(request)
    }

    Après effectivement il faut optimiser les images (tailles), c'est peut-être ce qui est un peu lourd...


     


    Je veux bien ta solution pour la carte. Je pense que créé une classe model qui charge les fichiers au démarrage serait optimum.


     


    D'avance merci

  • CéroceCéroce Membre, Modérateur
    novembre 2017 modifié #4

    Je me demandais s'il était possible de précharger mes 4/5 fichiers HTML pour rendre mon application plus responsive. Les fichiers HTML sont intégrés à  mon Bundle.

    En relisant, je ne suis plus sûr de comprendre le problème.
    Veux-tu dire qu'habituellement, l'HTML est chargé sur le réseau et que tu souhaiterais déplacer quelques fichiers dans l'appli pour gagner du temps ?

    Question idiote: ne peut-on pas fournir une File URL à  WKWebView ?



  • Question idiote: ne peut-on pas fournir une File URL à  WKWebView ?




     


    Effectivement ça simplifie le code mais ça n'améliore pas les performances.



    func loadWebView(_ webView: WKWebView, fileName: String) {
    // Check File
    guard let url = Bundle.main.url(forResource: fileName,
    withExtension: "html") else {
    print ("HTML File not found: \(fileName)")
    return
    }

    // Load Page
    webView.loadFileURL(url, allowingReadAccessTo: Bundle.main.bundleURL)
    }

    Le mieux serait de pré chargé les pages dans le VC qui vont servir de menu pour ensuite les afficher ou te pré chargé dans l'app delegate mais je ne vois pas ce que vous voulez dire avec vos "cartes".

  • Bonjour !


     


    iLandes, j'ai justement pré chargé ma carte dans l'appDelegate.


    C'est la solution que je te propose.


     


    Voici mon code de l'appDelegate :



    var map: UIViewController?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    map = storyboard.instantiateViewController(withIdentifier: "MapViewController")
    return true
    }

    J'ai juste une question : pour les images, peux-tu les inclure dans les assets ? Je demande cela, car tu pourrais ainsi bénéficier d'un temps de chargement moins long. Et oui, il faut éviter de faire redimensionner les images par iOS.


  • LeChatNoirLeChatNoir Membre, Modérateur

    En fait, je comprends pas bien ton soucis.


    Afficher du HTML stocké sur le téléphone en local, c'est du quasi immédiat.


    Pourquoi tu parle de pb de perfs ?


    :o


  • Ca met une seconde pour charger la page. Je pense que tout est lié aux images inclues dans le HTML. Quelqu'un sait si on peut faire appel aux images de Assets depuis un fichier HTML. Quelque chose comme <img src = "/assets/myimage.png"> et si cela permettrait de gérer efficacement les résolution @1, @2, @3 ?


  • Pour gérer les images dans assets, tu peux utiliser le nom des images.


    Pour les résolutions @x1, @x2 et @x3, je pense que c'est fait automatiquement car dans Swift, tu peux insérer une image par son nom et l'application charge la bonne résolution. Attends tout de même la confirmation de Céroce ou de Joanna Carter, j'ai peut-être dis une grosse bêtise !!


     


    Cependant, je doute que l'on puisse faire appel aux images de assets depuis un fichier HTML. Le top pour toi serait de trouver la solution pour que tu puisses gérer les images avec Swift d'un côté, et gérer tes pages HTML de l'autre. Peux-tu nous en dire plus pour que nous puissions t'aider ?


  • iLandesiLandes Membre
    novembre 2017 modifié #10

    En gros j'ai des fichiers HTML avec des images stockée dans le main Bundle. Le CSS est plus haut dans ce post et les HTML sont comme cela :



    <!doctype html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Société</title>
    <link href="style.css" rel="stylesheet" type="text/css">
    </head>
    <body style="background-image: url(RMSLogo.png)">
    <div id="wrapper">
    <h1>
    Société
    </h1>
    <div>text text text text text text text text text text text text text text text text .
    </div>
    <img src="image.jpg">
    </body>
    </html>



  • Pour les résolutions @x1, @x2 et @x3, je pense que c'est fait automatiquement car dans Swift, tu peux insérer une image par son nom et l'application charge la bonne résolution.




     


    C'est absolument vrai. La bonne image sera chargé en fonction du device mais ça iLandes le savait déjà .


     


    Il veut savoir si un code HTML local peut charger une image locale. Pour des raisons de perfs et que la bonne image sera sélectionnée (d'un point de vu résolution) contrairement à  une image distante où se sera la même quelque soit ton device.


  • Ca met une seconde pour charger la page. Je pense que tout est lié aux images inclues dans le HTML. Quelqu'un sait si on peut faire appel aux images de Assets depuis un fichier HTML. Quelque chose comme <img src = "/assets/myimage.png"> et si cela permettrait de gérer efficacement les résolution @1, @2, @3 ?



     

     

    Pour les résolutions lié aux images j'ai trouvé cela cela pourra peut être t'aider.


  • CéroceCéroce Membre, Modérateur
    novembre 2017 modifié #13

    Comme on ne passe pas par Cocoa, les @1x etc ne vont pas fonctionner, mais en HTML on peut gérer ça avec les media queries, il me semble.


    Mais avant d'optimiser, il faut déjà  mesurer.


  • DrakenDraken Membre
    novembre 2017 modifié #14

    La structure de tes fichiers HTLM n'a pas l'air bien compliqué. Tu ne peux pas les parser pour récupérer les données dans une classe et afficher le contenu dans une View ? Ou encore écrire directement les données dans un plist ?


  • Parser le HTML vers une view ne me semble pas approprié dans mon cas. Les .html ne sont pas complexes mais ils sont différents.


  • As tu essayer en mode "AirPlane" ? Peut être la webview recherche certaine resources sur le net (en tout cas tente de le faire).


     


    Tu pourrais éventuellement reprendre ton tout premier exemple (dans le post d'origine) et renseigner baseURL avec l'URL ou se trouvent les ressources ?

  • iLandesiLandes Membre
    novembre 2017 modifié #17


    Comme on ne passe pas par Cocoa, les @1x etc ne vont pas fonctionner, mais en HTML on peut gérer ça avec les media queries, il me semble.


    Mais avant d'optimiser, il faut déjà  mesurer.




    Effectivement faut mesurer.


     


    Temps entre la demande de chargement et  func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) :


     


    - 0.79 secondes pour les images non optimisées et 0.03 au rechargement du même VC


    - 0.76 Sans image ni CSS (juste du texte) et  et 0.02 au rechargement du même VC


     


    CQFD : Même une fois les images optimisées on ne gagne que quelques centièmes de secondes au premier chargement. Par contre si on pouvait pré charger les VC et passe de 0.7 à  0.02 ce serait top.


  • iLandesiLandes Membre
    novembre 2017 modifié #18

    Bon finalement et parce qu'il faut bien finir pas livré. Je vais optimiser les images uniquement pour le principe car ce n'est pas ce qui me fait gagner le plus dans l'histoire. Je vais surtout créé une classe Model en Singleton qui me fournira mes WebView. Cela déplace le temps de latence au lancement de l'application ce qui est bien mieux que pendant la navigation.


     


    Juste un petit truc qui me manque et que j'ai pas trop le temps de chercher vu que je suis à  la bourre :


    Comment remonter le scroll de ma WebWiew dans le viewWillAppear() ?


     


    A suivre...


     


    Voici un extrait du code de mon Model :



    class WebPages {
    static let sharedInstance = WebPages()

    let companyPage: WKWebView = {
    let webConfiguration = WKWebViewConfiguration()
    let webView = WKWebView(frame: CGRect.zero, configuration: webConfiguration)

    // Load page
    guard let url = Bundle.main.url(forResource: "company",
    withExtension: "html") else {
    print ("HTML File not found")
    return webView
    }
    webView.loadFileURL(url, allowingReadAccessTo: Bundle.main.bundleURL)
    return webView
    }()
    }

Connectez-vous ou Inscrivez-vous pour répondre.