Ok, using Nimrod's suggestion, here is how I did it:
//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;
}
}
I've made a few minor changes to my code for presentation, but it is basically the same as I'm using. The HTML string in preparePage could be moved out for production code.
Edit: a change I've made since which might be useful to others is modifying appendMessage(msg) to create new div elements, instead of text nodes. This is useful if the text you are injecting includes HTML that you want to preserve.
function appendMessage(msg) {
var msgNode = document.createElement('div');
msgNode.innerHTML = msg;
var logNode = document.getElementById('log');
logNode.appendChild(msgNode);
}