stringByEvaluatingJavaScriptFromString не всегда работает - PullRequest
1 голос
/ 12 сентября 2011

Я занимаюсь разработкой приложения Objective C, которое загружает большой HTML-документ в UIWebView, когда пользователь просматривает его. Это связано с тем, что размер документа составляет 20 МБ, и он может привести к сбою веб-просмотра, если загружается все сразу. Идея состоит в том, что документ разбивается на куски 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;
}

Код Objective C запускается в событии $ (document) .ready () jQuery с использованием следующего кода:

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

Если я прошагаю по коду, то я вижу, что запускается метод stringByEvaluatingJavaScriptFromString, который либо возвращает «добавленный» в качестве результата, либо иногда возвращаемый указатель недопустим. В веб-представлении не отображаются оповещения, и html не добавляется в nextHtmlToAdd, кажется, что только первый бит HTML правильно передается в UIWebView.

Что мне было интересно, так это ли ограничение на длину строки javascript, которую может выполнять stringByEvaluatingJavaScriptFromString, или на количество раз, которое она может быть выполнена? Есть ли альтернативные способы сделать это?

Спасибо

Джо

1 Ответ

4 голосов
/ 12 сентября 2011

Да, существуют ограничения на метод stringByEvaluatingJavaScriptFromString.Две вещи, о которых вам нужно знать:

  • Запрещено выделение JavaScript размером более 10 МБ
  • Запрещено выполнение JavaScript, выполнение которого длится более 10 секунд

В первом случае вы получите сгенерированное исключение, но во втором оно вполне может завершиться «тихо».Вы проверяете возвращаемое значение метода?Если это не удастся, он вернет nil.Это может быть полезным способом узнать, завершается ли ваш скрипт операционной системой по одной из указанных выше причин.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...