UIWebview常常會用到和原生頁面的跳轉(zhuǎn),有的可能還需要傳值跳轉(zhuǎn)。自己寫了1個自定義跳轉(zhuǎn)的webview,可以跳轉(zhuǎn)到指定控制器并傳值,這需要和后臺協(xié)商好,html中如何傳值跳轉(zhuǎn),即:html中的跳轉(zhuǎn)按鈕關(guān)聯(lián)的js方法如何書寫。
html中的測試代碼以下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF⑻">
<title>Title</title>
</head>
<script type="text/javascript">
//以下為寫死的數(shù)據(jù)直接跳轉(zhuǎn),原則上后臺能動態(tài)的給出對應(yīng)的值并通過點擊事件傳值到原生方法中,到達傳值并跳轉(zhuǎn)原生頁面的效果。
//controllerName對應(yīng)的名字為原生頁面控制器的類名
//controllerProperties則是字典,包括了上面控制器對應(yīng)的屬性名和值,相當于鍵值對,即需要傳給原生頁面的值
//A控制器需要傳的值
var controllerNameA = "AViewController";
var controllerPropertiesA = { "prodId": "1001", "prodName": "吸塵器", "prodPrice": "50元" };
//B控制器需要傳的值
var controllerNameB = "BViewController";
var controllerPropertiesB = { "petId": "1002", "petName": "趴趴熊", "petPrice": "100萬" };
//C控制器需要傳的值
var controllerNameC = "CViewController";
var controllerPropertiesC = { "personId": "1003", "personName": "Tom", "personSex": "變態(tài)" };
//這里定義了跳轉(zhuǎn)方法,點擊事件會履行下面的方法并傳至給原生方法
function jumpToController(controllerName,controllerProperties) {
}
</script>
<body bgcolor="#555555">
<!--下面為3個跳轉(zhuǎn)到對應(yīng)頁面的按鈕-->
<button type="button" onclick="jumpToController(controllerNameA,controllerPropertiesA)">點擊傳至并跳轉(zhuǎn)到A控制器</button>
<button type="button" onclick="jumpToController(controllerNameB,controllerPropertiesB)">點擊傳至并跳轉(zhuǎn)到B控制器</button>
<button type="button" onclick="jumpToController(controllerNameC,controllerPropertiesC)">點擊傳至并跳轉(zhuǎn)到C控制器</button>
</body>
</html>
上面的jumpToController方法即為跳轉(zhuǎn)方法,點擊按鈕后會對應(yīng)的把值傳到方法中并履行大括號內(nèi)種的內(nèi)容,內(nèi)容里面甚么都沒有,這其實不重要,我們的目的只是把值傳到方法里,原生頁面通過JavaScriptCore可以知道履行了這個方法和傳過來的值足已,由于跳轉(zhuǎn)頁面只需要控制器名和對應(yīng)的屬性值。
首先需要定義3個控制器。
AViewController,BViewController,CViewController,里面定義好測試的屬性(其實應(yīng)當是先做的控制器,html根據(jù)原生頁面的具體類名和屬性來傳值),這里我們以A屬性為例:
#import <UIKit/UIKit.h>
@interface AViewController : UIViewController
@property(nonatomic, copy) NSString *prodId;
@property(nonatomic, copy) NSString *prodName;
@property(nonatomic, copy) NSString *prodPrice;
@end
控制器中m文件輸出數(shù)據(jù)。
在進入頁面后打印這些屬性,如果最后有值傳過來,那末打印出來的肯定不是空值。
#import "AViewController.h"
@interface AViewController ()
@end
@implementation AViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"A";
self.view.backgroundColor = [UIColor grayColor];
NSLog(@"屬性分別是prodId:%@,prodName:%@,prodPrice:%@", self.prodId, self.prodName, self.prodPrice);
// Do any additional setup after loading the view.
}
初始頁面添加JSContext屬性并加載html文件。
這里加載之前寫的那個html文件:
#import "ViewController.h"
#import <JavaScriptCore/JavaScriptCore.h>
#import <objc/Runtime.h>
@interface ViewController () <UIWebViewDelegate>
@property(nonatomic, weak) IBOutlet UIWebView *webView;
@property(nonatomic, weak) JSContext *context;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self webViewConfig];
// Do any additional setup after loading the view, typically from a nib.
}
/**設(shè)置本地網(wǎng)頁,并讀取之*/
- (void)webViewConfig {
self.title = @"初始網(wǎng)頁";
NSString *path = [[NSBundle mainBundle] pathForResource:@"jstest" ofType:@"html"];
NSLog(@"%@", path);
NSURL *url = [[NSURL alloc] initFileURLWithPath:path];
NSLog(@"%@", url);
NSURLRequest *request = [NSURLRequest requestWithURL:url];
self.webView.delegate = self;
[self.webView loadRequest:request];
}
/**設(shè)置JS環(huán)境,這里需要在網(wǎng)頁讀取以后*/
- (void)webViewDidFinishLoad:(UIWebView *)webView {
/**獲得全局的js環(huán)境*/
self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
/**描寫html里的方法jumpToController如何履行*/
self.context[@"jumpToController"] = ^{
/**args為獲得這個方法傳過來的參數(shù),得到的是JSValue對象,和后臺協(xié)商好,傳過來就只有1個字符串和1個字典,字符串放控制器名稱,字典的key和value對應(yīng)屬性名和其值*/
NSArray *args = [JSContext currentArguments];
Class controllerClass = nil;
NSDictionary *parameters = nil;
/**遍歷從js傳過來的值,這里只有兩個,1個字符串1個字典,字符串為類名,字典為需要的屬性*/
for (JSValue *jsVal in args) {
/**傳過來的值是字符串,說明是控制器名字*/
if ([jsVal isString]) {
NSString *controllerName = [jsVal toString];
controllerClass = NSClassFromString(controllerName);
}
/**傳過來的值是對象,說明存的是參數(shù),那末使用字典接收*/
if ([jsVal isObject]) {
parameters = [jsVal toDictionary];
}
}
/**拿到類名和屬性,直接生成控制器賦值(務(wù)必保證傳過來的字符串是正確的控制器類名)*/
UIViewController *viewController = (UIViewController *) [[controllerClass alloc] init];//既然已是傳的正確的控制器名,那末這里1定可以強轉(zhuǎn)成功。
/**給控制器賦值*/
[viewController setValuesForKeysWithDictionary:parameters];
/**頁面跳轉(zhuǎn)*/
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController pushViewController:viewController animated:YES];
});
};
}
原則上來說,html中的傳值,是1樣可以做到動態(tài)傳的,也即是說可以動態(tài)傳值跳轉(zhuǎn),這個demo其實可以進1步進行封裝,加上加載條等,作為1個基礎(chǔ)網(wǎng)頁控制器。
demo下載地址:https://github.com/JeffreyWW/JFJSCoreTest
歡迎交換,QQ:25105483