UIWebView 如何 怎麼 運行 JavaScript Js

來源:互聯網
上載者:User

WebKit on the iPhone (Part 1)

If you develop an application which should display a web page or HTML file, you can use the WebKit framework, which is part of the MacOS and also of the iPhone OS.

But while on the Mac, the WebKit framework provides almost 160 public header files which define even more public classes and tons of methods you can call to get control of all aspects of loading, rendering, displaying and modifying a web page, on the iPhone there’s only one single class (UIWebView) with has just about a dozen methods you can use. Though internally the UIWebView class uses the same WebKit framework that is available on the Mac as public API, this API is private on the iPhone and therefore can’t be used. The small number of methods of the UIWebView class are sufficient to display nicely formatted text in help screens for example, but for a web browser (like iCab Mobile) or other web-based apps this isn’t enough, many essential features are missing.

Some examples:

  • UIWebView doesn’t provide a method to get the title of the currently displayed web page,
  • it just ignores all attempts to open links which are meant to open in new windows or tabs
  • it doesn’t allow accessing the HTML tree

WebKit itself provides many classes for all these tasks, but all of them are private and not available on the iPhone.

Some of the alternative browsers which are available in the AppStore just declare these limitations as feature (for example they advertise the inability to open new windows or Tabs as “no anoying popup window”). This sounds great, but of course this doesn’t make such browsers useful in the real world.

So what can we do to overcome these limitations of the UIWebView class? Can we (re)implement all the cool features of the WebKit framework which is available on the Mac on the iPhone as well without violating the  iPhone SDK agreements with Apple? Unfortunately, we can’t. But we can implement many of the missing feature.

If you look at the available methods, there’s only one, which would allow access to the content of the web page, and this is more or less the only way to get back  the missing features. And this method is

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

This method is used to execute JavaScript code in the context of the current web page and get back a string as result. This means that we have to use JavaScript code to implement the features we need.

Let’s start with something that is very easy. We implement methods to get the title and the URL of the currently displayed web page. We implement this as an Objective C “Category”, so we don’t need to subclass UIWebView:

File: MyWebViewAdditions.h

@interface UIWebView (MyWebViewAdditions)- (NSString*)title;- (NSURL*)url;@end

File: MyWebViewAdditions.m

#import "MyWebViewAdditions.h"@implementation UIWebView (MyWebViewAdditions)- (NSString*)title{    return [self stringByEvaluatingJavaScriptFromString:@"document.title"];}- (NSURL*)url{    NSString *urlString = [self stringByEvaluatingJavaScriptFromString:@"location.href"];    if (urlString) {        return [NSURL URLWithString:urlString];    } else {        return nil;    }}@end

What are we doing here?
From the JavaScript’s point of view a web page is represented by the “document” object which has several properties. One of the properties is the “title” property which contains the title of the page. So with “document.title” we can access the title of the document within JavaScript. And this is exactly what we need to pass as a parameter to the method “stringByEvaluatingJavaScriptFromString:” to get the document title.

For retreiving the URL we do something similar.

So whenever we need to get the title or URL of the web page that is displayed in a UIWebView object, we only need to call the “title” or “url” method:

NSString *title = [anyUIWebViewObject title];

The next limitation we may want to address is the inability to open links which would open in a new window. The WebKit on the Mac would just call a delegate method of the host application to request that a new WebView object is created for an URL request. The application would then create a new WebView object and load the new page there. But on the iPhone the UIWebView doesn’t support such a delegate method and so all attempts to open such a link are just ignored.

These links do usually look like this:

<a href="destination" target="_blank">Link Text</a>

The “target” attribute defines where the link will open. The value can be a name of a frame (if the web page has frames), the name of a window or some reserved target names like “_blank” (opens a new window), “_self” (the window itself), “_parent” (the parent frame, if there are nested frames) and “_top” (the top-level or root frame, or identical to “_self” if the page doesn’t use frames).

As a first step, we want to tap on a such a link in our iPhone App, and the link should open like any other normal link in the same UIWebView object. What we need to do is simple: we need to find all links with a “target” attribute set to “_blank” and change its value to “_self“. Then the UIWebView object will no longer ignore these links. To be able to modify all of the link targets we have to wait until the page has finished loading and the whole web page content is available. Fortunately UIWebView provides the delegate method

- (void)webViewDidFinishLoad:(UIWebView *)webView;

which will be called when the web page has finished loading. So we have everything we need: We get notified when the page has loaded, and we know a way to access and modify the web page content (using “stringByEvaluatingJavaScriptFromString:“).

First we write our JavaScript code. Because this will be a little bit more code than what was needed to get the document title, it’s a good idea to create an extra file for our JavaScript code and then we add this file to the resources of our project in XCode:

File: ModifyLinkTargets.js:

function MyIPhoneApp_ModifyLinkTargets() {    var allLinks = document.getElementsByTagName('a');    if (allLinks) {        var i;        for (i=0; i<allLinks.length; i++) {            var link = allLinks[i];            var target = link.getAttribute('target');            if (target && target == '_blank') {                link.setAttribute('target','_self');            }        }    }}

What is this JavaScript function doing, when called?
It gets an array of all links (“a” tags) and then loops through all of these tags, checks if there’s a target attribute with the value “_blank“. If this is the case it changes the value to “_self“.

Note: There are other tags which can have a “target” attribute, like the “form” tag and the “area” tag. So you can use the “getElementsByTagName()” call to get these tags as well and modify their target attributes in the same way as I’ve done this for the “a” tag.

In our iPhone App we need to define a delegate for the UIWebView object and this delegate object will be called whenever the web page has finished loading. This is the method that is called in the delegate by the UIWebView object:

- (void)webViewDidFinishLoad:(UIWebView *)webView{    NSString *path = [[NSBundle mainBundle] pathForResource:@"ModifyLinkTargets" ofType:@"js"];    NSString *jsCode = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];    [webView stringByEvaluatingJavaScriptFromString:jsCode];    [webView stringByEvaluatingJavaScriptFromString:@"MyIPhoneApp_ModifyLinkTargets()"];}

What is this code doing?
At first the access path of the JavaScript file we created before is retreived from the application bundle and we load the content of the file (the JavaScript code) into a string. Then we execute/inject this code into the web page and finally we call out JavaScript function
which is modifying the link targets.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.