UIWebView與WKWebView,JavaScript的與OC交互,餅干管理看我就夠(轉(zhuǎn)載)

?iOS中的UIWebView與WKWebView,JavaScript的與OC交互,餅干管理看我就夠(上)

前言

iOS的開(kāi)發(fā)中,用來(lái)顯示一個(gè)HTML頁(yè),H5頁(yè),經(jīng)常會(huì)用的一個(gè)控件是的WebView。說(shuō)到的WebView,你知道多少呢?是簡(jiǎn)單的展示,還是要和OC交互實(shí)現(xiàn)比較復(fù)雜的功能呢?本文將為您介紹的iOS中的WebView中,并且由淺到深,一步步帶你了解并掌握的WebView的用法,JavaScript的與目標(biāo)的交互,以及餅干的管理,JS的調(diào)試等。

文章因涉及到的內(nèi)容較多,因此拆分成以下幾部分:

的iOS中的UIWebView與WKWebView,JavaScript的與OC交互,餅干管理看我就夠(上)

iOS中UIWebView與WKWebView,JavaScript與OC交互,Cookie管理看我就夠(中)(已發(fā)布??)

iOS中UIWebView與WKWebView,JavaScript與OC交互,Cookie管理看我就夠(下)(已發(fā)布??)

關(guān)于文中提到的一些內(nèi)容,這里我準(zhǔn)備了個(gè)Demo,有需要的小伙可以下載。

本文目錄

前言

UIWebView的

UIWebView的基本用法

一個(gè)UIWebView中的JavaScript與目標(biāo)的交互

UIWebView OC調(diào)用JS

stringByEvaluatingJavaScriptFromString:

JavaScriptCore(iOS 7.0 +)

UIWebView JS調(diào)用OC

自定義網(wǎng)址方案(受保護(hù)網(wǎng)址)

JavaScriptCore(iOS 7.0 +)

UIWebView中的Cookie的管理

餅干簡(jiǎn)介

曲奇管理

未完待續(xù)

UIWebView的

UIWebView的基本用法

首先要介紹的就是我們的老朋友UIWebView。相信對(duì)大多數(shù)小伙伴兒而言,UIWebView狀語(yǔ)從句:UILabel一樣,都是最早接觸的控件了,其實(shí)UIWebView用法英語(yǔ)諺語(yǔ)比較簡(jiǎn)單(功能基本能滿足需求),簡(jiǎn)單的創(chuàng)建,并且調(diào)用

- (void)loadRequest:(NSURLRequest*)request;- (void)loadHTMLString:(NSString*)string baseURL:(nullableNSURL*)baseURL;- (void)loadData:(NSData*)data MIMEType:(NSString*)MIMEType textEncodingName:(NSString*)textEncodingName baseURL:(NSURL*)baseURL;

這些方法,加載就可以了。

當(dāng)然,如果需要監(jiān)聽(tīng)頁(yè)面加載的結(jié)果,或者需要判斷是否允許打開(kāi)某個(gè)URL,需要那設(shè)置UIWebView的delegate,只代理需要遵循協(xié)議,并且在代理中實(shí)現(xiàn)下面的這些可選方法就可以:

__TVOS_PROHIBITED@protocolUIWebViewDelegate@optional- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType;- (void)webViewDidStartLoad:(UIWebView*)webView;- (void)webViewDidFinishLoad:(UIWebView*)webView;- (void)webView:(UIWebView*)webView didFailLoadWithError:(nullableNSError*)error;@end

一個(gè)UIWebView中的JavaScript與目標(biāo)的交互

這里不詳細(xì)討論一些很好的第三方實(shí)現(xiàn),比如WebViewJavascriptBridge單純的講講native端JS與OC的交互實(shí)現(xiàn)方式,讀完了下面的部分,相信你也會(huì)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的bridge了。

UIWebView OC調(diào)用JS

1. stringByEvaluatingJavaScriptFromString:

最常用的方法,很簡(jiǎn)單,調(diào)用只要- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;就可以了,如:

self.navigationItem.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];

雖然比較方便,但是缺點(diǎn)也有:

該方法不能判斷調(diào)用了一個(gè)JS方法之后,是否發(fā)生了錯(cuò)誤。當(dāng)錯(cuò)誤發(fā)生時(shí),返回值為零,而當(dāng)調(diào)用一個(gè)方法本身沒(méi)有返回值時(shí),返回值也為零,所以無(wú)法判斷是否調(diào)用成功了。

返回值類(lèi)型為nullable NSString *,就意味著當(dāng)調(diào)用的JS方法有返回值時(shí),都以字符串返回,不夠靈活。當(dāng)返回值是一個(gè)JS的陣列時(shí),還需要解析字符串,比較麻煩。

對(duì)于上述缺點(diǎn),可以通過(guò)使用JavaScriptCore(iOS 7.0 +)來(lái)解決。

2. JavaScriptCore(iOS 7.0 +)

想必大家不會(huì)陌生吧,弄前些日子的沸沸揚(yáng)揚(yáng)的JSPatch被禁事件中,最核心的就是它了。因?yàn)镴avaScriptCore的JS到OC的映射,可以替換各種JS方法成OC方法,其所以動(dòng)態(tài)性(配合運(yùn)行時(shí)的不安全性)也就成為了JSPatch被蘋(píng)果禁掉的最主要原因。講這里下UIWebView通過(guò)JavaScriptCore來(lái)實(shí)現(xiàn)OC-> JS。

其實(shí)WebKit的都有一個(gè)內(nèi)嵌的JS環(huán)境,一般我們?cè)陧?yè)面加載完成之后,獲取JS上下文,通過(guò)然后JSContext的evaluateScript:方法來(lái)獲取報(bào)道查看值。該因?yàn)榈玫椒椒ǖ牡挠⑽囊粋€(gè)JSValue對(duì)象,所以支持的JavaScript的數(shù)組,數(shù)字,字符串,對(duì)象等數(shù)據(jù)類(lèi)型。

- (void)webViewDidFinishLoad:(UIWebView*)webView{//更新標(biāo)題,這是上面的講過(guò)的方法//self.navigationItem.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];//獲取該UIWebView的javascript上下文JSContext *jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];//這也是一種獲取標(biāo)題的方法。JSValue *value = [self.jsContext evaluateScript:@"document.title"];//更新標(biāo)題self.navigationItem.title = value.toString;}

方法該解決了stringByEvaluatingJavaScriptFromString:報(bào)道查看值只是NSString的問(wèn)題。

那么如果我執(zhí)行了一個(gè)不存在的方法,比如

[self.jsContext evaluateScript:@"document.titlexxxx"];

那么必然會(huì)報(bào)錯(cuò),報(bào)錯(cuò)了,可以通過(guò)@property (copy) void(^exceptionHandler)(JSContext *context, JSValue *exception);,設(shè)置該塊來(lái)獲取異常。

//在調(diào)用前,設(shè)置異常回調(diào)[self.jsContext setExceptionHandler:^(JSContext *context, JSValue *exception){NSLog(@"%@",exception);}];//執(zhí)行方法JSValue *value = [self.jsContext evaluateScript:@"document.titlexxxx"];

該方法,很好也。解決的了stringByEvaluatingJavaScriptFromString:調(diào)用JS方法后,出現(xiàn)錯(cuò)誤卻捕獲不到的缺點(diǎn)。

UIWebView JS調(diào)用OC

1.自定義URL方案(被攔截的URL)

比如darkangel://。方法是在html或者js中,點(diǎn)擊某個(gè)按鈕觸發(fā)事件時(shí),跳轉(zhuǎn)到自定義URL Scheme構(gòu)造的鏈接,而Objective-C中捕獲該鏈接,從中解析必要的參數(shù),實(shí)現(xiàn)JS到OC的一次交互比如頁(yè)面中一個(gè)一個(gè)標(biāo)簽,鏈接如下:

短信驗(yàn)證登錄

而在目標(biāo)C中,遵循只要了UIWebViewDelegate協(xié)議,那么每次打開(kāi)一個(gè)鏈接之前,都會(huì)觸發(fā)方法

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType;

在該方法中,捕獲該鏈接,并且返回NO(阻止本次跳轉(zhuǎn)),從而執(zhí)行對(duì)應(yīng)的OC方法。

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType{//標(biāo)準(zhǔn)的URL包含scheme、host、port、path、query、fragment等NSURL*URL = request.URL;if([URL.scheme isEqualToString:@"darkangel"]) {if([URL.host isEqualToString:@"smsLogin"]) {NSLog(@"短信驗(yàn)證碼登錄,參數(shù)為 %@", URL.query);returnNO;}}returnYES;}

當(dāng)用戶點(diǎn)擊短信驗(yàn)證登錄時(shí),控制臺(tái)會(huì)輸出短信驗(yàn)證碼登錄,參數(shù)為 username=12323123&code=892845。參數(shù)可以是一個(gè)json格式并且URLEncode過(guò)的字符串,這樣就可以實(shí)現(xiàn)復(fù)雜參數(shù)的傳遞(比如WebViewJavascriptBridge)。

優(yōu)點(diǎn):泛用性強(qiáng),可以配合H5實(shí)現(xiàn)頁(yè)面動(dòng)態(tài)化比如頁(yè)面中一個(gè)活動(dòng)鏈接到活動(dòng)詳情頁(yè),當(dāng)本地尚未開(kāi)發(fā)完畢時(shí),鏈接可以是一個(gè)H5鏈接,等到本地開(kāi)發(fā)完畢時(shí),可以通過(guò)該方法跳轉(zhuǎn)到本地頁(yè)面,實(shí)現(xiàn)頁(yè)面動(dòng)態(tài)化。且該方案適用于安卓和iOS版,泛用性很強(qiáng)。

缺點(diǎn):無(wú)法直接獲取本次交互的返回值,比較適合單向傳參,且不關(guān)心回調(diào)的情景,比如H5頁(yè)面跳轉(zhuǎn)到本地頁(yè)面等。

其實(shí),WebViewJavascriptBridge使用的方案就是攔截URL,為了解決無(wú)法直接獲取返回值的缺點(diǎn),它采用了將一個(gè)名為callback的function作為參數(shù),通過(guò)一些封裝,傳遞到OC(js-> oc傳遞參數(shù)和callbackId),然后在OC端執(zhí)行完畢,再通過(guò)block來(lái)回調(diào)回調(diào)(oc-?> js,傳遞返回值參數(shù)),實(shí)現(xiàn)異步獲取返回值,比如在js端調(diào)用

//JS調(diào)用OC的分享方法(當(dāng)然需要OC提前注冊(cè))share為方法名,shareData為參數(shù),后面的為回調(diào)functionWebViewJavascriptBridge.callHandler('share', shareData,function(response){//OC端通過(guò)block回調(diào)分享成功或者失敗的結(jié)果alert(response);});

具體的可以看下它的源碼,還是很值得學(xué)習(xí)的。

2. JavaScriptCore(iOS 7.0 +)

除了攔截網(wǎng)址的方法,還可以利用上面提到的JavaScriptCore,它十分強(qiáng)大,強(qiáng)大在哪里呢?下面我們來(lái)一探究竟。

當(dāng)然,還是需要在頁(yè)面加載完成時(shí),先獲取JS上下文。獲取到之后,我們就可以進(jìn)行強(qiáng)大的方法映射了。

比如JS中我定義了一個(gè)分享的方法

functionshare(title, imgUrl, link){//這里需要OC實(shí)現(xiàn)}

在OC中實(shí)現(xiàn)如下

- (void)webViewDidFinishLoad:(UIWebView*)webView{//將js的function映射到OC的方法[selfconvertJSFunctionsToOCMethods];}- (void)convertJSFunctionsToOCMethods{//獲取該UIWebview的javascript上下文//self持有jsContext//@property (nonatomic, strong) JSContext *jsContext;self.jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];//js調(diào)用oc//其中share就是js的方法名稱(chēng),賦給是一個(gè)block 里面是oc代碼//此方法最終將打印出所有接收到的參數(shù),js參數(shù)是不固定的self.jsContext[@"share"] = ^() {NSArray*args = [JSContext currentArguments];//獲取到share里的所有參數(shù)//args中的元素是JSValue,需要轉(zhuǎn)成OC的對(duì)象NSMutableArray*messages = [NSMutableArrayarray];for(JSValue *objinargs) {[messages addObject:[obj toObject]];}NSLog(@"點(diǎn)擊分享js傳回的參數(shù):\n%@", messages);};}

在HTML或者JS的某處,點(diǎn)擊一個(gè)標(biāo)簽調(diào)用這個(gè)共享方法,并傳參,如

分享活動(dòng),領(lǐng)30元紅包

此時(shí),如果用戶點(diǎn)擊了分享活動(dòng),領(lǐng)30元紅包這個(gè)標(biāo)簽,那么在控制臺(tái)會(huì)打印出所有參數(shù)

上面的代碼實(shí)現(xiàn)了OC方法替換JS實(shí)現(xiàn)。它十分靈活,主要依賴這些API。

@interfaceJSContext(SubscriptSupport)/*!

@method

@abstract Get a particular property on the global object.

@result The JSValue for the global object's property.

*/- (JSValue *)objectForKeyedSubscript:(id)key;/*!

@method

@abstract Set a particular property on the global object.

*/- (void)setObject:(id)object forKeyedSubscript:(NSObject *)key;

self.jsContext[@"yourMethodName"] = your block;寫(xiě)這樣不僅可以在有yourMethodName方法時(shí)替換該JS方法為OC實(shí)現(xiàn),還會(huì)在該方法沒(méi)有時(shí),添加方法。簡(jiǎn)而言之,有則替換,無(wú)則添加

那如果我想寫(xiě)一個(gè)有兩個(gè)參數(shù),一個(gè)返回值的JS方法,OC應(yīng)該怎么替換呢?

JS中

//該方法傳入兩個(gè)整數(shù),求和,并返回結(jié)果functiontestAddMethod(a, b){//需要OC實(shí)現(xiàn)a+b,并返回returna + b;}//js調(diào)用console.log(testAddMethod(1,5));//output? 6

OC直接替換該方法

self.jsContext[@"testAddMethod"] = ^NSInteger(NSIntegera,NSIntegerb) {returna + b;};

那么當(dāng)在JS調(diào)用

//js調(diào)用console.log(testAddMethod(1,5));//output? 6, 方法為 a + b

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

self.jsContext[@"testAddMethod"] = ^NSInteger(NSIntegera,NSIntegerb) {returna * b;};

再次調(diào)用JS

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

舉一反三,調(diào)用方法原實(shí)現(xiàn),并且在原結(jié)果上乘以10。

//調(diào)用方法的本來(lái)實(shí)現(xiàn),給原結(jié)果乘以10JSValue *value =self.jsContext[@"testAddMethod"];self.jsContext[@"testAddMethod"] = ^NSInteger(NSIntegera,NSIntegerb) {JSValue *resultValue = [value callWithArguments:[JSContext currentArguments]];returnresultValue.toInt32 *10;};

再次調(diào)用JS

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

上面的方法,都是同步函數(shù),如果我想實(shí)現(xiàn)JS調(diào)用OC的方法,并且異步接收回調(diào),那么該怎么做呢?比如H5中有一個(gè)分享按鈕,用戶點(diǎn)擊之后,調(diào)用本地分享(微信分享,微博分享等),在天然分享成功或者失敗時(shí),回調(diào)H5頁(yè)面,告訴其分享結(jié)果,H5頁(yè)面刷新對(duì)應(yīng)的UI,顯示分享成功或者失敗。

這個(gè)問(wèn)題,需要對(duì)JS有一定了解。下面上的js代碼。

//聲明functionshare(shareData){vartitle = shareData.title;varimgUrl = shareData.imgUrl;varlink = shareData.link;varresult = shareData.result;//do something//這里模擬異步操作setTimeout(function(){//2s之后,回調(diào)true分享成功result(true);},2000);}//調(diào)用的時(shí)候需要這么寫(xiě)share({title:"title",imgUrl:"http://img.dd.com/xxx.png",link: location.href,result:function(res){//函數(shù)作為參數(shù)console.log(res ?"success":"failure");}});

從封裝的角度上講,JS的share方法的參數(shù)的英文一個(gè)對(duì)象,該對(duì)象包含了幾個(gè)必要的字段,以及一個(gè)回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)有點(diǎn)像OC的block,調(diào)用者把一個(gè)function傳入一個(gè)function當(dāng)作參數(shù),在適當(dāng)時(shí)候,內(nèi)方法實(shí)現(xiàn)者調(diào)用該function,對(duì)實(shí)現(xiàn)調(diào)用者的異步回調(diào)那么如果此時(shí)OC來(lái)實(shí)現(xiàn)。share方法,該怎么做呢其實(shí)大概是這樣的?

//異步回調(diào)self.jsContext[@"share"] = ^(JSValue *shareData) {//首先這里要注意,回調(diào)的參數(shù)不能直接寫(xiě)NSDictionary類(lèi)型,為何呢?//仔細(xì)看,打印出的確實(shí)是一個(gè)NSDictionary,但是result字段對(duì)應(yīng)的不是block而是一個(gè)NSDictionary? NSLog(@"%@", [shareData toObject]);//獲取shareData對(duì)象的result屬性,這個(gè)JSValue對(duì)應(yīng)的其實(shí)是一個(gè)javascript的function。JSValue *resultFunction = [shareData valueForProperty:@"result"];//回調(diào)block,將js的function轉(zhuǎn)換為OC的blockvoid(^result)(BOOL) = ^(BOOLisSuccess) {[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);});};

其中一些坑,已經(jīng)在代碼的注釋寫(xiě)的比較清楚了,要這里注意JavaScript的function狀語(yǔ)從句:Objective-C的block的轉(zhuǎn)換。

從上面的一些探討和嘗試來(lái)看,證明足以JavaScriptCore的強(qiáng)大,這里不再展開(kāi),小伙伴們可以自行探索。

UIWebView中的Cookie的管理

餅干簡(jiǎn)介

說(shuō)到Cookie,或許有些小伙伴會(huì)比較陌生,有些小伙伴會(huì)比較熟悉。如果項(xiàng)目中,所有頁(yè)面都是純?cè)鷣?lái)實(shí)現(xiàn)的話,一般Cookie這個(gè)東西或許我們永遠(yuǎn)也。不會(huì)接觸到。但是,這里還是要說(shuō)一下Cookie,因?yàn)樗娴暮苤匾伤a(chǎn)生的一些坑也很多。

Cookie在網(wǎng)絡(luò)利用的最多的地方,是用來(lái)記錄各種狀態(tài)。你比如在Safari中打開(kāi)_百度,然后登陸自己的賬號(hào),之后打開(kāi)所有百度相關(guān)的頁(yè)面,都會(huì)是登陸狀態(tài),而且當(dāng)你關(guān)了電腦,下開(kāi)機(jī)次再次打開(kāi)Safari打開(kāi)_百度,會(huì)發(fā)現(xiàn)還是登陸狀態(tài),其實(shí)這個(gè)就利用了Cookie。Cookie中記錄了你百度賬號(hào)的一些信息,有效期等,也維持了跨域請(qǐng)求時(shí)登錄狀態(tài)的統(tǒng)計(jì)性。

看到可以Cookie的域各不相同,有效期也各不相同,一般.baidu.com這樣的域的Cookie就是為了跨域時(shí),可以維持一些狀態(tài)。

那么在應(yīng)用程序中,Cookie的最常用的就是維持登錄狀態(tài)了。一般本地端都有自己的一套完整登錄注冊(cè)邏輯,一般大部分頁(yè)面都是原生實(shí)現(xiàn)的。當(dāng)然,也會(huì)有一些頁(yè)面是H5來(lái)實(shí)現(xiàn)的,雖然h5頁(yè)面在App中通過(guò)WebView加載或多或少都會(huì)有點(diǎn)性能問(wèn)題,感覺(jué)不流暢或者體驗(yàn)不好,但是它的靈活性是Native App無(wú)法比擬的。那么由此,便產(chǎn)生了一種需求,當(dāng)本地端用戶是登錄狀態(tài)的,打開(kāi)一個(gè)H5頁(yè)面,H5也要維持用戶的登錄狀態(tài)。

這個(gè)需求看似簡(jiǎn)單,如何實(shí)現(xiàn)呢?一般的解決方案是本地保存登錄狀態(tài)的餅干,在打開(kāi)H5頁(yè)面中,把餅干添加上,以此來(lái)維持登錄狀態(tài)。其實(shí)坑還是有很多的,比如用戶登錄或者退出了,H5頁(yè)面的登錄狀態(tài)也變了,需要刷新,什么時(shí)候刷新?WKWebView中Cookie丟失問(wèn)題?簡(jiǎn)單這里說(shuō)下UIWebView的Cookie管理,后面的章節(jié)再介紹WKWebView。

曲奇管理

UIWebView的Cookie管理很簡(jiǎn)單,一般不需要我們手動(dòng)操作Cookie,所有因?yàn)镃ookie都會(huì)被[NSHTTPCookieStorage sharedHTTPCookieStorage]這個(gè)單例管理,而且UIWebView會(huì)自動(dòng)同步CookieStorage中的Cookie的,所以只要我們?cè)诒镜囟耍5顷懲顺觯琀5在適當(dāng)時(shí)候刷新,就可以正確的維持登錄狀態(tài),不需要做多余的操作。

可能有一些情況下,我們需要在訪問(wèn)某個(gè)鏈接時(shí),一個(gè)添加固定Cookie用來(lái)做區(qū)分,就那么可以通過(guò)header來(lái)實(shí)現(xiàn)

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

也可以主動(dòng)操作NSHTTPCookieStorage,添加一個(gè)自定義Cookie

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

還有一些常用的方法,如讀取所有Cookie

NSArray*cookies = [NSHTTPCookieStoragesharedHTTPCookieStorage].cookies;

Cookie轉(zhuǎn)換成HTTPHeaderFields,并到添加request的header中

//Cookies數(shù)組轉(zhuǎn)換為requestHeaderFieldsNSDictionary*requestHeaderFields = [NSHTTPCookierequestHeaderFieldsWithCookies:cookies];//設(shè)置請(qǐng)求頭request.allHTTPHeaderFields = requestHeaderFields;

來(lái)說(shuō)本世紀(jì)的牛頓UIWebView的Cookie管理比較簡(jiǎn)單,小伙伴們可以自己寫(xiě)個(gè)演示測(cè)試一下,發(fā)揮你們的想象。

未完待續(xù)

關(guān)于UIWebView的介紹,使用以及UIWebView進(jìn)行JS與OC的交互,Cookie的管理,就先簡(jiǎn)單介紹到這里。如果有小伙伴對(duì)于WebViewJavascriptBridge比較感興趣,可以留言,根據(jù)留言我考慮一下寫(xiě)一篇文章,分析它的詳細(xì)實(shí)現(xiàn)。

另外,將為后續(xù)介紹您WKWebView的用法英語(yǔ)諺語(yǔ),一些OC與JS交互,餅干管理,在如何Safari中調(diào)試以及一些不為人知的坑等,敬請(qǐng)期待?

后續(xù)文章已發(fā)布:

iOS中UIWebView與WKWebView,JavaScript與OC交互,Cookie管理看我就夠(中)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,401評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,069評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,873評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,635評(píng)論 6 408
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,128評(píng)論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,365評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,881評(píng)論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,733評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,935評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,172評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,582評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,821評(píng)論 1 282
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,595評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,908評(píng)論 2 372

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