简体   繁体   English

stringByEvaluatingJavaScriptFromString似乎并不总是有效

[英]stringByEvaluatingJavaScriptFromString doesn't always seem to work

I am developing an Objective C application that loads a large HTML document in to a UIWebView as the user scrolls through it. 我正在开发一个Objective C应用程序,当用户滚动它时,它将大型HTML文档加载到UIWebView中。 This is because the document is 20Mb and tends to crash the webview if loaded all at once. 这是因为文档是20Mb,如果一次加载,往往会导致webview崩溃。 The idea is that the document is split in to chunks of HTML and as the user scrolls through it new elements are added to the document and old elements are removed. 我们的想法是将文档拆分为HTML块,并在用户滚动浏览时将新元素添加到文档中,并删除旧元素。

Currently I am working on getting the Objective C application to pass data to a javascript function within the document. 目前我正致力于将Objective C应用程序传递给文档中的javascript函数。 I have the following Objective C code: 我有以下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();"]);
}

I have the following javascript within the document: 我在文档中有以下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;
}

The Objective C code is triggered in jQuery's $(document).ready() event using the following code: 使用以下代码在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;

If I step through the code then what I see is the stringByEvaluatingJavaScriptFromString method being run and either returning 'appended' as a result or sometimes the returned pointer is invalid. 如果我单步执行代码,那么我看到的是运行的stringByEvaluatingJavaScriptFromString方法,并且返回'附加'作为结果或有时返回的指针无效。 No alerts appear within the web view and the html doesn't get appended to nextHtmlToAdd, only the first bit of HTML seems to be getting passed to the UIWebView correctly. Web视图中没有出现警报,并且html没有附加到nextHtmlToAdd,只有HTML的第一位似乎正在正确地传递给UIWebView。

What I was wondering is if there is a limit on either the length of the javascript string that stringByEvaluatingJavaScriptFromString can execute or the number of times that it can be executed? 我想知道的是,stringByEvaluatingJavaScriptFromString可以执行的javascript字符串的长度是否有限制,或者它可以执行的次数是多少? Are there any alternative ways of doing this? 有没有其他方法可以做到这一点?

Thanks, 谢谢,

Joe

Yes, there are limits placed upon the stringByEvaluatingJavaScriptFromString method. 是的, stringByEvaluatingJavaScriptFromString方法有限制。 The two you need to know about: 你需要知道的两个:

  • JavaScript allocations greater than 10MB are not allowed 不允许大于10MB的JavaScript分配
  • JavaScript that takes longer than 10 seconds to execute is not allowed 不允许执行时间超过10秒的JavaScript

In the former, you'll get an exception generated, but in the latter it may well fail 'silently'. 在前者中,您将获得异常,但在后者中,它可能会“无声地”失败。 Are you testing the return value of the method? 您是否正在测试该方法的返回值? If it fails it will return nil . 如果失败,它将返回nil This can be a useful way to see if your script is being terminated by the OS due to one of the reasons above. 由于上述原因之一,这可以是查看操作系统是否终止脚本的有用方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM