现在的位置: 首页 > 综合 > 正文

使用UIWebView时objective-c与javascript互相调用 1

2014年02月28日 ⁄ 综合 ⁄ 共 4471字 ⁄ 字号 评论关闭

原文转自:http://zonble.net/archives/2010_09/1385.php
在写 JavaScript 的时候,可以使用一个叫做 window 的对象,像是我们想要从现在的网页跳到另外一个网页的时候,就会去修改 window.location.href 的位置;在我们的 Objective C 程序码中,如果我们可以取得指定的 WebView 的指标,也就可以拿到这个出现在 JavaScript 中的 window 对象,也就是 [webView windowScriptObject]。

这个对象就是 WebView 里头的 JS 与我们的 Obj C 程序之间的桥樑-window 对象可以取得网页里头所有的 JS 函数与对象,而如果我们把一个 Obj C 对象设定成 windowScriptObject 的 value,JS 也便可以调用
Obj C 对象的 method。于是,我们可以在 Obj C 程序里头要求 WebView 执行一段 JS,也可以反过来让 JS 调用一段用 Obj C 实作的功能。

※ 用 Objective C 取得与设定 JavaScript 对象

要从 Obj C 取得网页中的 JavaScript 对象,也就是对 windowScriptObject 做一些 KVC 调用,像是 valueForKey: 与 valueForKeyPath:。如果我们在 JS 里头,想要知道目前的网页位置,会这麽写:

1
  1. varlocation = window.location.href;  
varlocation = window.location.href;

用 ObjC 就可以这麽调用:

1
  1.       
  2. NSString*location = [[webView windowScriptObject] valueForKeyPath:@"location.href"];  
	
NSString*location = [[webView windowScriptObject] valueForKeyPath:@"location.href"];

如果我们要设定 window.location.href,要求开启另外一个网页,在 JS 里头:

1
  1.       
  2. window.location.href ='http://spring-studio.net';  
	
window.location.href ='http://spring-studio.net';

Obj C:

1
 
  1. [[webView windowScriptObject] setValue:@"http://spring-studio.net"forKeyPath:@"location.href"];  
[[webView windowScriptObject] setValue:@"http://spring-studio.net"forKeyPath:@"location.href"];

由于 Obj C 与 JS 本身的语言特性不同,在两种语言之间相互传递东西之间,就可以看到两者的差别-

  • JS 虽然是 OO,但是并没有 class,所以将 JS 对象传到 Obj C 程序里头,除了基本字串会转换成 NSString、基本数字会转成 NSNumber,像是 Array 等其他对象,在 Obj C 中,都是 WebScriptObject 这个 Class。意思就是,JS 的 Array 不会帮你转换成 NSArray。
  • 从 JS 里头传一个空对象给 Obj C 程序,用的不是 Obj C 里头原本表示「没有东西」的方式,像是 NULL、nil、NSNull 等,而是专属 WebKit 使用的 WebUndefined。

所以,如果我们想要看一个 JS Array 里头有什麽东西,就要先取得这个对象里头叫做 length 的 value,然后用 webScriptValueAtIndex: 去看在该 index 位置的内容。假如我们在 JS 里头这样写:

1
2
3
4
 
  1. varJSArray = {'zonble','dot','net'};  
  2. for(vari = 0; i < JSArray.length; i++) {  
  3.     console.log(JSArray[i]);  
  4. }  
varJSArray = {'zonble','dot','net'};
for(vari = 0; i < JSArray.length; i++) {
    console.log(JSArray[i]);
}


 

Obj C 里头就会变成这样:

1
2
3
4
5
6
7
8
 
  1. WebScriptObject *obj = (WebScriptObject *)JSArray;  
  2. NSUIntegercount = [[obj valueForKey:@"length"] integerValue];  
  3. NSMutableArray*a = [NSMutableArrayarray];  
  4. for(NSUIntegeri = 0; i < count; i++) {  
  5.     NSString*item = [obj webScriptValueAtIndex:i];  
  6.     NSLog(@"item:%@", item);  
  7. }  
WebScriptObject *obj = (WebScriptObject *)JSArray;
NSUIntegercount = [[obj valueForKey:@"length"] integerValue];
NSMutableArray*a = [NSMutableArrayarray];
for(NSUIntegeri = 0; i < count; i++) {
    NSString*item = [obj webScriptValueAtIndex:i];
    NSLog(@"item:%@", item);
}


 


用 Objective C 调用 JavaScript function

要用 Obj C 调用网页中的 JS function,大概有几种方法。第一种是直接写一段跟你在网页中会撰写的 JS 一模一样的程序,叫 windowScriptObject 用 evaluateWebScript: 执行。例如,我们想要在网页中产生一个新的
JS function,内容是:

1
2
3
 
  1. functionx(x) {  
  2.     returnx + 1;  
  3. }  
functionx(x) {
    returnx + 1;
}


 

所以在 Obj C 中可以这样写;

1
  1.       
  2. [[webView windowScriptObject] evaluateWebScript:@"function x(x) { return x + 1;}"];  
	
[[webView windowScriptObject] evaluateWebScript:@"function x(x) { return x + 1;}"];

接下来我们就可以调用 window.x():

1
2
 
  1. NSNumber*result = [[webView windowScriptObject] evaluateWebScript:@"x(1)"];  
  2. NSLog(@"result:%d", [result integerValue]);// Returns 2  
NSNumber*result = [[webView windowScriptObject] evaluateWebScript:@"x(1)"];
NSLog(@"result:%d", [result integerValue]);// Returns 2


 

由于在 JS 中,每个 funciton 其实都是对象,所以我们还可以直接取得 window.x 叫这个对象执行自己。在 JS 里头如果这样写:

1
  1.       
  2. window.x.call(window.x, 1);  
	
window.x.call(window.x, 1);

Obj C 中便是这样:

1
2
 
  1. WebScriptObject *x = [[webView windowScriptObject] valueForKey:@"x"];  
  2. NSNumber*result = [x callWebScriptMethod:@"call"withArguments:[NSArrayarrayWithObjects:x, [NSNumbernumberWithInt:1],nil]];  
WebScriptObject *x = [[webView windowScriptObject] valueForKey:@"x"];
NSNumber*result = [x callWebScriptMethod:@"call"withArguments:[NSArrayarrayWithObjects:x, [NSNumbernumberWithInt:1],nil]];


 

这种让某个 WebScriptObject 自己执行自己的写法,其实比较不会用于从 Obj C 调用 JS 这一端,而是接下来会提到的,由 JS 调用 Obj C,因为这样 JS 就可以把一个 callback function 送到 Obj C 程序里头。

如果我们在做网页,我们只想要更新网页中的一个区块,就会利用 AJAX 的技巧,只对这个区块需要的资料,对 server 发出 request,并且在 request 完成的时候,要求执行一段 callback function,更新这一个区块的显示内容。从
JS 调用 Obj C也可以做类似的事情,如果 Obj C 程序里头需要一定时间的运算,或是我们可能是在 Obj C 里头抓取网路资料,我们便可以把一个 callback function 送到 Obj C 程序裡,要求 Obj C 程序在做完工作后,执行这段 callback function。


DOM

WebKit 里头,所有的 DOM 对象都继承自 DOMObject,DOMObject 又继承自 WebScriptObject,所以我们在取得了某个 DOM 对象之后,也可以从 Obj C 程序中,要求这个 DOM 对象执行 JS 程序。

假如我们的网页中,有一个 id 叫做 “#s” 的文字输入框(text input),而我们希望现在键盘输入的焦点放在这个输入框上,在 JS 里头会这样写:

1
 
  1. document.querySelector('#s').focus();  
document.querySelector('#s').focus();

Obj C:

1
2
 

抱歉!评论已关闭.