1. 程式人生 > >UIWebview交互之自己定義傳值跳轉

UIWebview交互之自己定義傳值跳轉

tag 跳轉頁面 demo sel nsbundle 控制器名 ref click pic

UIWebview常常會用到和原生頁面的跳轉。有的可能還須要傳值跳轉。自己寫了一個自己定義跳轉的webview,能夠跳轉到指定控制器並傳值,這須要和後臺協商好。html中怎樣傳值跳轉,即:html中的跳轉按鈕關聯的js方法怎樣書寫。

html中的書寫

html中的測試代碼例如以下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script
type="text/javascript">
//以下為寫死的數據直接跳轉,原則上後臺能動態的給出相應的值並通過點擊事件傳值到原生方法中,達到傳值並跳轉原生頁面的效果。 //controllerName相應的名字為原生頁面控制器的類名 //controllerProperties則是字典,包括了上面控制器相應的屬性名和值。相當於鍵值對,即須要傳給原生頁面的值 //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": "變態" }; //這裏定義了跳轉方法。點擊事件會運行以下的方法並傳至給原生方法 function jumpToController(controllerName,controllerProperties) { }
</script> <body bgcolor="#555555"> <!--以下為3個跳轉到相應頁面的按鈕--> <button type="button" onclick="jumpToController(controllerNameA,controllerPropertiesA)">點擊傳至並跳轉到A控制器</button> <button type="button" onclick="jumpToController(controllerNameB,controllerPropertiesB)">點擊傳至並跳轉到B控制器</button> <button type="button" onclick="jumpToController(controllerNameC,controllerPropertiesC)">點擊傳至並跳轉到C控制器</button> </body> </html>

上面的jumpToController方法即為跳轉方法,點擊按鈕後會相應的把值傳到方法中並運行大括號內種的內容,內容裏面什麽都沒有,這並不重要。我們的目的僅僅是把值傳到方法裏。原生頁面通過JavaScriptCore能夠知道運行了這種方法和傳過來的值足已,由於跳轉頁面僅僅須要控制器名和相應的屬性值。


原生頁面中

  • 首先須要定義3個控制器。

    AViewController,BViewController,CViewController。裏面定義好測試的屬性(事實上應該是先做的控制器,html依據原生頁面的詳細類名和屬性來傳值),這裏我們以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文件輸出數據。

    在進入頁面後打印這些屬性,假設最後有值傳過來。那麽打印出來的肯定不是空值。

#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.
}

/**設置本地網頁,並讀取之*/
- (void)webViewConfig {
    self.title = @"初始網頁";
    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];
}
  • 關鍵點,獲取到全局的js環境並拿到值進行跳轉。

    須要寫在webViewDidFinishLoad裏,代碼例如以下:

/**設置JS環境。這裏須要在網頁讀取之後*/
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    /**獲取全局的js環境*/
    self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    /**描寫敘述html裏的方法jumpToController怎樣運行*/
    self.context[@"jumpToController"] = ^{
        /**args為獲取這種方法傳過來的參數,得到的是JSValue對象,和後臺協商好。傳過來就僅僅有一個字符串和一個字典,字符串放控制器名稱,字典的key和value相應屬性名和其值*/
        NSArray *args = [JSContext currentArguments];
        Class controllerClass = nil;
        NSDictionary *parameters = nil;
        /**遍歷從js傳過來的值,這裏僅僅有兩個,一個字符串一個字典,字符串為類名,字典為須要的屬性*/
        for (JSValue *jsVal in args) {
            /**傳過來的值是字符串,說明是控制器名字*/
            if ([jsVal isString]) {
                NSString *controllerName = [jsVal toString];
                controllerClass = NSClassFromString(controllerName);
            }
            /**傳過來的值是對象,說明存的是參數,那麽使用字典接收*/
            if ([jsVal isObject]) {
                parameters = [jsVal toDictionary];
            }
        }
        /**拿到類名和屬性,直接生成控制器賦值(務必保證傳過來的字符串是正確的控制器類名)*/
        UIViewController *viewController = (UIViewController *) [[controllerClass alloc] init];//既然已經是傳的正確的控制器名。那麽這裏一定能夠強轉成功。

/**給控制器賦值*/ [viewController setValuesForKeysWithDictionary:parameters]; /**頁面跳轉*/ dispatch_async(dispatch_get_main_queue(), ^{ [self.navigationController pushViewController:viewController animated:YES]; }); }; }

  • A界面進入後,顯示打印結果,即為html中傳的值。(請忽略界面不是xcode細節)。
    技術分享

原則上來講,html中的傳值,是一樣能夠做到動態傳的。也即是說能夠動態傳值跳轉,這個demo事實上能夠進一步進行封裝,加上載入條等,作為一個基礎網頁控制器。
demo下載地址:https://github.com/JeffreyWW/JFJSCoreTest
歡迎交流,QQ:25105483

UIWebview交互之自己定義傳值跳轉