OC--UIWebView的JS與OC交互汉额、Cookie管理

完全抄錄:
iOS中UIWebView與WKWebView、JavaScript與OC交互榨汤、Cookie管理看我就夠(上)
深入淺出 JavaScriptCore
JavaScriptCore框架詳解

UIWebView OC調(diào)用JS

1蠕搜、stringByEvaluatingJavaScriptFromString

/*缺點
1、所以無法判斷是否調(diào)用成功收壕,失敗返回nil讥脐,js本身方法返回是nil
2、返回值是NSString啼器,其他類型數(shù)據(jù)需要轉換解析
*/
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

self.navigationItem.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
  1. JavaScriptCore(iOS 7.0 +)
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    //更新標題旬渠,這是上面的講過的方法
    //self.navigationItem.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];

    //獲取該UIWebView的javascript上下文
    JSContext *jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    //這也是一種獲取標題的方法。
    JSValue *value = [self.jsContext evaluateScript:@"document.title"];
    //更新標題
    self.navigationItem.title = value.toString;
}
//在調(diào)用前端壳,設置異掣娑回調(diào)
[self.jsContext setExceptionHandler:^(JSContext *context, JSValue *exception){
        NSLog(@"%@", exception);
}];
//執(zhí)行方法
JSValue *value = [self.jsContext evaluateScript:@"document.titlexxxx"];
UIWebView JS調(diào)用OC
  1. Custom URL Scheme(攔截URL)
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    //標準的URL包含scheme、host损谦、port岖免、path、query照捡、fragment等
    NSURL *URL = request.URL;    
    if ([URL.scheme isEqualToString:@"darkangel"]) {
        if ([URL.host isEqualToString:@"smsLogin"]) {
            NSLog(@"短信驗證碼登錄颅湘,參數(shù)為 %@", URL.query);
            return NO;// NO(阻止本次跳轉)
        }
    }
    return YES;
}

優(yōu)點:泛用性強,可以配合h5實現(xiàn)頁面動態(tài)化栗精。比如頁面中一個活動鏈接到活動詳情頁闯参,當native尚未開發(fā)完畢時,鏈接可以是一個h5鏈接悲立,等到native開發(fā)完畢時鹿寨,可以通過該方法跳轉到native頁面,實現(xiàn)頁面動態(tài)化薪夕。且該方案適用于Android和iOS脚草,泛用性很強。

缺點:無法直接獲取本次交互的返回值原献,比較適合單向傳參馏慨,且不關心回調(diào)的情景埂淮,比如h5頁面跳轉到native頁面等。

  1. JavaScriptCore(iOS 7.0 +)

OC現(xiàn)實JS的方法
JS代碼

function share(title, imgUrl, link) {
     //這里需要OC實現(xiàn)
}

OC代碼

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    //將js的function映射到OC的方法
    [self convertJSFunctionsToOCMethods];
}

- (void)convertJSFunctionsToOCMethods
{
    //獲取該UIWebview的javascript上下文
    //self持有jsContext
    self.jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    //js調(diào)用oc
    //其中share就是js的方法名稱写隶,賦給是一個block 里面是oc代碼
    //此方法最終將打印出所有接收到的參數(shù)倔撞,js參數(shù)是不固定的
    // ja的"share",有則替換樟澜,無則添加。
    self.jsContext[@"share"] = ^() {
        NSArray *args = [JSContext currentArguments];//獲取到share里的所有參數(shù)
        //args中的元素是JSValue叮盘,需要轉成OC的對象
        NSMutableArray *messages = [NSMutableArray array];
        for (JSValue *obj in args) {
            [messages addObject:[obj toObject]];
        }
        NSLog(@"點擊分享js傳回的參數(shù):\n%@", messages);
    };
}

一個有兩個參數(shù)秩贰,一個返回值的js方法
JS

//該方法傳入兩個整數(shù),求和柔吼,并返回結果
function testAddMethod(a, b) {
     //需要OC實現(xiàn)a+b毒费,并返回
      return a + b;
}

console.log(testAddMethod(1, 5));    //output  6

OC直接替換該方法

self.jsContext[@"testAddMethod"] = ^NSInteger(NSInteger a, NSInteger b) {
      return a + b;
};

JS調(diào)用

console.log(testAddMethod(1, 5));    //output  6, 方法為 a + b

OC替換該方法為兩數(shù)相乘

self.jsContext[@"testAddMethod"] = ^NSInteger(NSInteger a, NSInteger b) {
      return a * b;
};

JS調(diào)用

console.log(testAddMethod(1, 5));    //output  5愈魏,該方法變?yōu)榱?a * b觅玻。

OC調(diào)用方法原實現(xiàn),并且在原結果上乘以10

//調(diào)用方法的本來實現(xiàn)培漏,給原結果乘以10
JSValue *value = self.jsContext[@"testAddMethod"];
self.jsContext[@"testAddMethod"] = ^NSInteger(NSInteger a, NSInteger b) {
    JSValue *resultValue = [value callWithArguments:[JSContext currentArguments]];
    return resultValue.toInt32 * 10;
};

JS調(diào)用

console.log(testAddMethod(1, 5));    //output  60溪厘,該方法變?yōu)榱?a + b) * 10

回調(diào):
比如h5中有一個分享按鈕,用戶點擊之后牌柄,調(diào)用native分享(微信分享畸悬、微博分享等),在native分享成功或者失敗時珊佣,回調(diào)h5頁面蹋宦,告訴其分享結果,h5頁面刷新對應的UI咒锻,顯示分享成功或者失敗
JS代碼

//聲明(其實不需要聲明冷冗,因為原生注入代碼方法是:有則替換,無則添加)
function share(shareData) {

}

//調(diào)用的時候需要這么寫
share({
      title: "title", 
     imgUrl: "http://img.dd.com/xxx.png", 
     link: location.href, 
     result: function(res) {    //函數(shù)作為參數(shù)
         console.log(res ? "success" : "failure");
    }
});

OC代碼

//異步回調(diào)
self.jsContext[@"share"] = ^(JSValue *shareData) {    //首先這里要注意惑艇,回調(diào)的參數(shù)不能直接寫NSDictionary類型取试,為何呢?
    //仔細看疤估,打印出的確實是一個NSDictionary榛鼎,但是result字段對應的不是block而是一個NSDictionary  
      NSLog(@"%@", [shareData toObject]);     
    //獲取shareData對象的result屬性,這個JSValue對應的其實是一個javascript的function兢卵。
    JSValue *resultFunction = [shareData valueForProperty:@"result"];
    //回調(diào)block习瑰,將js的function轉換為OC的block
    void (^result)(BOOL) = ^(BOOL isSuccess) {
        [resultFunction callWithArguments:@[@(isSuccess)]];
    };
    //模擬異步回調(diào)
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"回調(diào)分享成功");
        result(YES);
    });
};
UIWebView的Cookie管理

UIWebView的Cookie管理很簡單,一般不需要我們手動操作Cookie秽荤,因為所有Cookie都會被[NSHTTPCookieStorage sharedHTTPCookieStorage]這個單例管理甜奄,而且UIWebView會自動同步CookieStorage中的Cookie柠横,所以只要我們在Native端,正常登陸退出课兄,h5在適當時候刷新牍氛,就可以正確的維持登錄狀態(tài),不需要做多余的操作烟阐。

可能有一些情況下搬俊,我們需要在訪問某個鏈接時,添加一個固定Cookie用來做區(qū)分蜒茄,那么就可以通過header來實現(xiàn)

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]];
[request addValue:@"customCookieName=1314521;" forHTTPHeaderField:@"Set-Cookie"];
[self.webView loadRequest:request];

也可以主動操作NSHTTPCookieStorage唉擂,添加一個自定義Cookie

NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:@{
    NSHTTPCookieName: @"customCookieName", 
    NSHTTPCookieValue: @"1314521", 
    NSHTTPCookieDomain: @".baidu.com",
    NSHTTPCookiePath: @"/"
}];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];    //Cookie存在則覆蓋,不存在添加

還有一些常用的方法檀葛,如讀取所有Cookie轉換成HTTPHeaderFields玩祟,并添加到request的header中

NSArray *cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies;
//Cookies數(shù)組轉換為requestHeaderFields
NSDictionary *requestHeaderFields = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
//設置請求頭
request.allHTTPHeaderFields = requestHeaderFields;
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市屿聋,隨后出現(xiàn)的幾起案子空扎,更是在濱河造成了極大的恐慌,老刑警劉巖润讥,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件转锈,死亡現(xiàn)場離奇詭異,居然都是意外死亡楚殿,警方通過查閱死者的電腦和手機黑忱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勒魔,“玉大人甫煞,你說我怎么就攤上這事」诰睿” “怎么了抚吠?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長弟胀。 經(jīng)常有香客問我楷力,道長,這世上最難降的妖魔是什么孵户? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任萧朝,我火速辦了婚禮,結果婚禮上夏哭,老公的妹妹穿的比我還像新娘检柬。我一直安慰自己,他們只是感情好竖配,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布何址。 她就那樣靜靜地躺著里逆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪用爪。 梳的紋絲不亂的頭發(fā)上原押,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音偎血,去河邊找鬼诸衔。 笑死,一個胖子當著我的面吹牛颇玷,可吹牛的內(nèi)容都是我干的笨农。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼亚隙,長吁一口氣:“原來是場噩夢啊……” “哼磁餐!你這毒婦竟也來了违崇?” 一聲冷哼從身側響起阿弃,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎羞延,沒想到半個月后渣淳,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡伴箩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年入愧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗤谚。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡棺蛛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出巩步,到底是詐尸還是另有隱情旁赊,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布椅野,位于F島的核電站终畅,受9級特大地震影響,放射性物質發(fā)生泄漏竟闪。R本人自食惡果不足惜离福,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望炼蛤。 院中可真熱鬧妖爷,春花似錦、人聲如沸理朋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至笋除,卻和暖如春斜友,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背垃它。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工鲜屏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人国拇。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓洛史,卻偏偏與公主長得像,于是被迫代替她去往敵國和親酱吝。 傳聞我的和親對象是個殘疾皇子也殖,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容