UIWebview交互之自定義傳值跳轉

UIWebview經(jīng)常會用到和原生頁面的跳轉,有的可能還需要傳值跳轉。自己寫了一個自定義跳轉的webview,可以跳轉到指定控制器并傳值,這需要和后臺協(xié)商好,html中如何傳值跳轉,即:html中的跳轉按鈕關聯(lián)的js方法如何書寫。

html中的書寫

html中的測試代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script type="text/javascript">
    //以下為寫死的數(shù)據(jù)直接跳轉,原則上后臺能動態(tài)的給出對應的值并通過點擊事件傳值到原生方法中,達到傳值并跳轉原生頁面的效果。
    //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": "變態(tài)" };
    //這里定義了跳轉方法,點擊事件會執(zhí)行下面的方法并傳至給原生方法
    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方法即為跳轉方法,點擊按鈕后會對應的把值傳到方法中并執(zhí)行大括號內種的內容,內容里面什么都沒有,這并不重要,我們的目的只是把值傳到方法里,原生頁面通過JavaScriptCore可以知道執(zhí)行了這個方法和傳過來的值足已,因為跳轉頁面只需要控制器名和對應的屬性值。


原生頁面中

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

    AViewController,BViewController,CViewController,里面定義好測試的屬性(其實應該是先做的控制器,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.
}

/**設置本地網(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];
}
  • 關鍵點,獲取到全局的js環(huán)境并拿到值進行跳轉。需要寫在webViewDidFinishLoad里,代碼如下:
/**設置JS環(huán)境,這里需要在網(wǎng)頁讀取之后*/
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    /**獲取全局的js環(huán)境*/
    self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    /**描述html里的方法jumpToController如何執(zhí)行*/
    self.context[@"jumpToController"] = ^{
        /**args為獲取這個方法傳過來的參數(shù),得到的是JSValue對象,和后臺協(xié)商好,傳過來就只有一個字符串和一個字典,字符串放控制器名稱,字典的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);
            }
            /**傳過來的值是對象,說明存的是參數(shù),那么使用字典接收*/
            if ([jsVal isObject]) {
                parameters = [jsVal toDictionary];
            }
        }
        /**拿到類名和屬性,直接生成控制器賦值(務必保證傳過來的字符串是正確的控制器類名)*/
        UIViewController *viewController = (UIViewController *) [[controllerClass alloc] init];//既然已經(jīng)是傳的正確的控制器名,那么這里一定可以強轉成功。
        /**給控制器賦值*/
        [viewController setValuesForKeysWithDictionary:parameters];
        /**頁面跳轉*/
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.navigationController pushViewController:viewController animated:YES];
        });
    };
}
  • A界面進入后,顯示打印結果,即為html中傳的值。(請忽略界面不是xcode細節(jié))。


    這里寫圖片描述

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容