UIWebView 加载解析的 html 字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1147687/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 00:18:12  来源:igfitidea点击:

UIWebView loading parsed html string

iphonehtmlstringuiwebviewparsing

提问by Sorin Antohi

i'm building an app that will display some newsletters to the users. the newsletters are displayed in a uiWebView. I'm reading the url's for the newsletters from an rss feed. I parse the xml, and in a table view i have all the newsletters. When a cell is clicked the uiWebView is pushed and the newsletter is loaded. Because the uiWebView doesn't open links that have target=_blank i need to replace the _blank from target with "". In an NSOperation i download the contents of the html and after the download is finished i replace the strings like this:

我正在构建一个应用程序,它将向用户显示一些时事通讯。时事通讯显示在 uiWebView 中。我正在阅读来自 rss 提要的时事通讯的网址。我解析了 xml,在表格视图中我有所有的时事通讯。单击单元格时,uiWebView 将被推送并加载时事通讯。因为 uiWebView 不会打开具有 target=_blank 的链接,所以我需要将 target 中的 _blank 替换为“”。在 NSOperation 中,我下载了 html 的内容,下载完成后,我替换了这样的字符串:

NSMutableString *page = [[[NSMutableString alloc] initWithData:pageData encoding:NSISOLatin1StringEncoding] autorelease]; [page replaceOccurrencesOfString:@"target=_blank" withString:@"target=""" options:0 range:NSMakeRange(0, [page length])];

after i do this i load the parsed string in the webView to display it to the user.

执行此操作后,我将解析后的字符串加载到 webView 中以将其显示给用户。

[myWebView loadHTMLString:page baseURL:[NSURL URLWithString:@""]];

while the NSOperation is downloading the contents of the page an HUD with a activity indicator and a label that says Loading is showed. When the download is finished the HUD is removed from the superview.

当 NSOperation 正在下载页面内容时,会显示一个带有活动指示器的 HUD 和一个显示正在加载的标签。下载完成后,HUD 将从超级视图中删除。

so far so good..but here come the questions. i used the NSOperation with the callback function because i wasn't able to determine the last call to webDidFinishLoading ( i read this UIWebView - How to identify the "last" webViewDidFinishLoad message?- this is a part of my problem but the response was to use some Apple private classes and that is a problem for me). so i'm doing this:

到目前为止一切顺利……但问题来了。我将 NSOperation 与回调函数一起使用,因为我无法确定对 webDidFinishLoading 的最后一次调用(我阅读了此UIWebView - 如何识别“最后一个” webViewDidFinishLoad 消息?- 这是我的问题的一部分,但响应是使用一些 Apple 私人课程,这对我来说是个问题)。所以我这样做:

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


NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
NSLog(@"WebViewSouldStartWithRequest: %@", urlString);
if (navigationType == UIWebViewNavigationTypeLinkClicked)
{
    if(![urlString isEqualToString:@"about:blank"])
    {
        NSLog(@"FeedViewController: startPageLoad");
        activityHud = [[HUDView alloc] initWithFrame:CGRectMake(110, 100, 80, 80)];
        [activityHud setText:@"Loading"];
        [myWebView addSubview:activityHud];
        NSLog(@"FeedViewController: pageUrl = %@", urlString);
        [self resetWebView];
        [urlLoader loadPageFromUrl:request.URL withCallbackTarget:self withCallbackSelector:@selector(endLoading:)];
    }
}

return NO;

}

}

- (void) endLoading:(NSMutableString *)page { [self resetWebView]; NSLog(@"FeedViewController: endLoading"); [activityHud removeFromSuperview]; [myWebView loadHTMLString:page baseURL:[NSURL URLWithString:@""]]; }

after i touch a cell in the table view and the newsletter is showed it looks like it should, when i click a link in the newsletter, the page is loaded with the new request, parsed but visually is not looking as it should (i looked at the page after parsing in NSLog and it has the css styles and html tags, head, body opened and closed correctly) anyone had this problem with uiWebView, not showing webpages correctly?

在我触摸表格视图中的一个单元格并显示时事通讯后,当我单击时事通讯中的链接时,页面加载了新请求,已解析但在视觉上看起来并不像它应该的那样(我看起来在 NSLog 中解析后的页面上,并且它具有 css 样式和 html 标签,头部、主体正确打开和关闭)任何人都遇到过 uiWebView 的问题,没有正确显示网页?

i tried loading the page with - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType{ return YES; }and in - (void)webViewDidFinishLoad:(UIWebView *)webview {} and in - webViewDiStartLoad

我尝试- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType{ return YES; }在 - (void)webViewDidFinishLoad:(UIWebView *)webview {} 和 - webViewDiStartLoad 中加载页面

but the methods are being called for every item that is loaded in the webview so showing and hiding the HUD in those method is not a good solution.

但是正在为 webview 中加载的每个项目调用这些方法,因此在这些方法中显示和隐藏 HUD 不是一个好的解决方案。

I encountered some problems while using - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { ... return NO }

我在使用时遇到了一些问题 - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { ... return NO }

for example links that have paths like this /bilder-galerien to not work and in NSLog i receive this for them

例如,具有像这样的路径的链接 /bilder-galerien 不起作用,在 NSLog 中我收到了这个

Unknown scheme, doing nothing: /bilder-galerien

未知方案,无所作为:/bilder-galerien

but when i use

但是当我使用

  • (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { return Yes } and didstartLoading and finishLoading the urls are loaded and i don't know why...
  • (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { return Yes } 和 didstartLoading 和 finishLoading 加载了网址,我不知道为什么......

another problem are the special german characters..in my first load(after pressing a cell in the uiTableView) the page is parsed like it should be by the uiWebView but after i click a link and the corresponding request is loaded also the characters are not parsed correctly..

另一个问题是特殊的德语字符..在我第一次加载时(在 uiTableView 中按下一个单元格后)页面被解析为 uiWebView 应该是这样,但是在我单击链接并加载相应的请求后,字符也不是解析正确..

can anyone point me in the good direction? thank you in advance

谁能指出我好的方向?先感谢您

采纳答案by Sorin Antohi

UIWebView doesn't open target="_blank" links. Certain links don't fire UIWebViewNavigationTypeLinkClicked events. This happens when the link has the target="_blank" attribute.

UIWebView 不会打开 target="_blank" 链接。某些链接不会触发 UIWebViewNavigationTypeLinkClicked 事件。当链接具有 target="_blank" 属性时会发生这种情况。

To work around this problem i used the code below. It injects some javascript after the page load to remove the target attribute from all the links. After using this code i didn;t needed anymore to parse the html source and replace _blank with _self for example.

为了解决这个问题,我使用了下面的代码。它在页面加载后注入一些 javascript 以从所有链接中删除目标属性。使用此代码后,我不再需要解析 html 源代码并将 _blank 替换为 _self 例如。

- (void)webViewDidFinishLoad:(UIWebView *)webView {
        NSString *js = @"\
        var d = document.getElementsByTagName('a');\
        for (var i = 0; i < d.length; i++) {\
            if (d[i].getAttribute('target') == '_blank') {\
                d[i].removeAttribute('target');\
            }\
        }\
        ";

        [webView stringByEvaluatingJavaScriptFromString:js];
}

回答by Mirek Rusin

I like SorinA answer, we can make it even better by:

我喜欢 SorinA 的回答,我们可以通过以下方式让它变得更好:

  • avoid obstructing javascript with var d
  • as we know we're running webkit engine we can use selectors:
  • 避免阻碍 javascript var d
  • 正如我们所知,我们正在运行 webkit 引擎,我们可以使用选择器:

...so in your UIWebViewDelegate protocol method invoke js code:

...所以在你的 UIWebViewDelegate 协议方法中调用 js 代码:

- (void) webViewDidFinishLoad: (UIWebView *) webView {
  [webView stringByEvaluatingJavaScriptFromString: @"(function($){for(var i=0;i<$.length;++i){$[i].removeAttribute('target')}})(document.querySelectorAll('a[target=_blank]'))"];
}