stringByEvaluatingJavaScriptFromString似乎并不总是有效

时间:2011-09-12 13:33:49

标签: javascript iphone objective-c ios uiwebview

我正在开发一个Objective C应用程序,当用户滚动它时,它将大型HTML文档加载到UIWebView中。这是因为文档是20Mb,如果一次加载,往往会导致webview崩溃。我们的想法是将文档拆分为HTML块,并在用户滚动浏览时将新元素添加到文档中,并删除旧元素。

目前我正致力于将Objective C应用程序传递给文档中的javascript函数。我有以下Objective C代码:

- (BOOL)webView:(UIWebView *)webView2 
shouldStartLoadWithRequest:(NSURLRequest *)request 
navigationType:(UIWebViewNavigationType)navigationType {

NSString *url = [[request URL] absoluteString];
// Intercept custom location change, URL begins with "js-call:"
if ([url hasPrefix:@"js-call:"]) {

    // Extract the selector name from the URL
    NSArray *components = [url componentsSeparatedByString:@":"];
    NSString *function = [components objectAtIndex:1];

    // Call the given selector
    [self performSelector:NSSelectorFromString(function)];

    // Cancel the location change
    return NO;
}

// Accept this location change
return YES;

}

- (void)loadNext {
int endIndex = [self.partIndexEnd intValue];
int newEndIndex = endIndex + 9;
if (newEndIndex >= [self.parts count] - 2){
    newEndIndex = [self.parts count] - 2;
}
if (endIndex == newEndIndex){
    return; // Already at the end of the document
}

int splitLen = 300;
NSRange range = NSMakeRange(endIndex, newEndIndex - endIndex);
for (NSString *html in [self.parts subarrayWithRange:range]) {
    NSLog(@"%@", html);
    NSString *htmlToSplit = html;
    while ([htmlToSplit length] > 0) {
        NSString *curHtml;
        if ([htmlToSplit length] <= splitLen){
            curHtml = htmlToSplit;
            htmlToSplit = @"";
        }
        else {
            curHtml = [htmlToSplit substringToIndex:splitLen + 1];
            htmlToSplit = [htmlToSplit substringFromIndex:splitLen - 1];
        }

        NSString* result = [self.web stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"next('%@');", [curHtml gtm_stringByEscapingForAsciiHTML]]];

        NSLog(@"START %@ END %@", curHtml, result);
    }

}   
[self.web stringByEvaluatingJavaScriptFromString:@"next(null);"];
NSLog(@"HTML = %@ *END*", [self.web stringByEvaluatingJavaScriptFromString:@"$('body').html();"]);
}

我在文档中有以下javascript:

var nextHtmlToAdd = '';
function next(html){
    var retval = '';
    try{
            if (html){
                    if (html.match(/teststring/i)){
                            alert('teststring');
                    }
                    nextHtmlToAdd = nextHtmlToAdd + html;
                    retVal = 'appended';
                    alert(html);
            } else {
                    // Finished sending HTML
                    alert('finished');
                    if (nextHtmlToAdd.match(/teststring/i)){
                            alert('encoded html contains teststring');
                    }

                    nextHtmlToAdd = $("<div/>").html(nextHtmlToAdd).text();
                    if (nextHtmlToAdd.match(/teststring/i)){
                            alert('html contains teststring');
                    }
                    alert(nextHtmlToAdd);
                    var elem = $(nextHtmlToAdd);
                    $('.endofsections').before(elem);
                    if (elem.text().match(/teststring/i)){
                            alert('element contains teststring');
                    }
                    if ($(document).text().match(/teststring/i)){
                            alert('document contains teststring');
                    }
                    nextHtmlToAdd = '';
                    retVal = 'finished';
            }
    } catch (err) {
            alert('Error: ' + err.description);
            retVal = 'error';
    }
    return retVal;
}

使用以下代码在jQuery的$(document).ready()事件中触发Objective C代码:

var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", "js-call:loadNext");
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;

如果我单步执行代码,那么我看到的是运行的stringByEvaluatingJavaScriptFromString方法,并且返回'附加'作为结果或有时返回的指针无效。 Web视图中没有出现警报,并且html没有附加到nextHtmlToAdd,只有HTML的第一部分似乎正在正确传递给UIWebView。

我想知道的是,stringByEvaluatingJavaScriptFromString可以执行的javascript字符串的长度是否有限制,或者它可以执行的次数是多少?有没有其他方法可以做到这一点?

谢谢,

1 个答案:

答案 0 :(得分:4)

是的,stringByEvaluatingJavaScriptFromString方法有限制。你需要知道的两个:

  • 不允许大于10MB的JavaScript分配
  • 不允许执行时间超过10秒的JavaScript

在前者中,你会产生异常,但在后者中它可能会“无声地”失败。您是否正在测试该方法的返回值?如果失败,它将返回nil。由于上述原因之一,这可以是查看操作系统是否终止脚本的有用方法。