2010-10-18 9 views
1

Mon application récupère du texte à partir d'un service Web en segments. J'affiche le texte formaté en utilisant un UIWebView. Jusqu'ici tout va bien.Utilisation d'un UIWebView pour afficher et regarder un journal

Mon problème est que chaque bloc arrive, j'ai besoin d'actualiser la vue web avec le nouveau contenu. J'utilise KVO pour observer les changements dans le texte, et quand le texte change j'appelle

[self loadHTMLString:self.log.text baseURL:nil]; 

pour réafficher la page avec le texte mis à jour. Malheureusement, cela recharge toute la page, réinitialisant la position actuelle des utilisateurs et le zoom.

Existe-t-il un moyen de demander à la vue web d'actualiser simplement le texte (en supposant qu'il le conserve), ou d'injecter du nouveau next/html dans la vue Web actuelle?

+0

À la fin du processus de chargement, vous réinitialisez la position et effectuez un zoom arrière sur les valeurs enregistrées. – vfn

+0

Bien que j'aime votre idée car elle laisse le modèle intact, il ne semble pas y avoir de méthodes ou de propriétés dans UIWebView pour obtenir ou définir le zoom et la position. Je pourrais le faire avec javascript, mais dans ce cas je ferais aussi bien de faire ce que Nimrod a suggéré, et j'utiliserais javascript pour injecter le nouveau texte (évitant tout rechargement) – Ashton

Répondre

1

Vous pouvez injecter du nouveau contenu dans une page à l'aide

(NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script 

et une fonction javascript de quelque sorte (comme peut-être innerHTML) pour ajouter du contenu au code HTML.

Malheureusement, je ne suis pas assez expert javascript pour donner un exemple pour la partie javascript. N'importe qui?

+0

Je ne connais pas beaucoup javascript, mais j'ai quelques personnes autour de moi qui le fais. Je vais devoir modifier un peu mon modèle pour que ça fonctionne, mais ça ira probablement mieux pour le moment. – Ashton

+0

Lorsque vous saurez de quoi il s'agit, veuillez le poster en commentaire ici. Je serais intéressé à savoir parce que je vais probablement vouloir l'utiliser à un moment donné. – Nimrod

+0

J'ai posté mon code dans une réponse ci-dessous, avec seulement quelques modifications mineures. – Ashton

1

Ok, en utilisant la suggestion de Nimrod, voici comment je l'ai fait:

//Called on first display. Sets up basic page, and a javascript function to 
//next log segments at the end of the a div 
- (void) preparePage{ 
    NSString *basePage = 
     @"<html><body>" 
     "<script type=\"text/javascript\">" 
      "function appendMessage(msg) {" 
       "var msgNode = document.createTextNode(msg);" 
       "var logNode = document.getElementById(\"log\");" 
       "logNode.appendChild(msgNode); }" 
     "</script>"  
     "<div id=\"log\" style=\"width:80em; white-space:pre-wrap;\"></div>" 
     "</body></html>"; 
    [self.logView loadHTMLString:basePage baseURL:nil]; 
    [self updateHTMLFromLog]; 
} 

//Called when the log has changed. Keeps track of current position, and inserts 
//new segments into the page using the javascript function created in preparePage 
- (void) updateHTMLFromLog{ 
    // loop through new log chunks, using Javascript to inject them into the page 
    while(self.logPosition < [self.log.segments count]){ 
     //escape double quotes to avoid breaking string 
     NSString *message = [self.log.segments objectAtIndex:self.logPosition] stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; 
     NSString *jsString = [NSString stringWithFormat:@"message = \"%@\";appendMessage(message);", message]; 
     [self.logView stringByEvaluatingJavaScriptFromString:jsString]; 
     ++self.logPosition; 
    } 
} 

J'ai fait quelques modifications mineures à mon code pour la présentation, mais il est fondamentalement la même chose que j'utilise. La chaîne HTML dans preparePage peut être déplacée pour le code de production.

Éditer: une modification que j'ai faite depuis qui pourrait être utile à d'autres est de modifier appendMessage (msg) pour créer de nouveaux éléments div, au lieu de nœuds de texte. Ceci est utile si le texte que vous injectez contient du code HTML que vous souhaitez conserver. Pourquoi ne sauvegardez-vous pas le zoom/la position en cours avant d'actualiser le contenu?

function appendMessage(msg) { 
    var msgNode = document.createElement('div'); 
    msgNode.innerHTML = msg; 
    var logNode = document.getElementById('log'); 
    logNode.appendChild(msgNode); 
} 
Questions connexes