一、UIWebView
什麼是UIWebView
UIWebView是iOS內置的瀏覽器控件
系統自帶的Safari瀏覽器就是經過UIWebView實現的html
UIWebView不但能加載遠程的網頁資源,還能加載絕大部分的常見文件
html\htm
pdf、doc、ppt、txt
mp4
… …web
UIWebView經常使用的加載資源的方法
- (void)loadRequest:(NSURLRequest *)request;數組
二、鍵盤工具條顯示中文瀏覽器
從新加載(刷新)
- (void)reload;工具
中止加載
- (void)stopLoading;post
回退
- (void)goBack;atom
前進
- (void)goForward;lua
須要進行檢測的數據類型
@property(nonatomic) UIDataDetectorTypes dataDetectorTypesurl
是否能回退
@property(nonatomic,readonly,getter=canGoBack) BOOL canGoBack;spa
是否能前進
@property(nonatomic,readonly,getter=canGoForward) BOOL canGoForward;
是否正在加載中
@property(nonatomic,readonly,getter=isLoading) BOOL loading;
是否伸縮內容至適應屏幕當前尺寸
@property(nonatomic) BOOL scalesPageToFit;
監聽UIWebView的加載過程
成爲UIWebView的代理,遵照UIWebViewDelegate協議,就能監聽UIWebView的加載過程
開始發送請求(加載數據)時調用這個方法
- (void)webViewDidStartLoad:(UIWebView *)webView;
請求完畢(加載數據完畢)時調用這個方法
- (void)webViewDidFinishLoad:(UIWebView *)webView;
請求錯誤時調用這個方法
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;
UIWebView在發送請求以前,都會調用這個方法,若是返回NO,表明中止加載請求,返回YES,表明容許加載請求
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
// Signature簽名: 在建立NSInvocation的時候, 必須傳遞一個簽名對象 // 簽名對象的做用 : 用於獲取參數的個數和方法的返回值 // 注意點: 建立簽名對象的時候不是使用NSMethodSignature類建立 \ 而是方法屬於誰就用誰來建立 NSMethodSignature *signature = [ViewController instanceMethodSignatureForSelector:@selector(sendMessageWithNumber:andContent:status:)]; // NSInvocation; 用來包裝方法和對應的對象, 它能夠存儲方法的名稱,對應的對象 ,對應的參數 // 1.建立一個NSInvocation對象 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.target = self; // 保存方法所屬的對象 // 給invocation設置的方法, 必須和簽名中的方法一致 invocation.selector = @selector(sendMessageWithNumber:andContent:status:); // 保存方法名稱 // 第一個參數: 須要給指定方法傳遞的值 // + 第一個參數須要接收一個指針, 也就是傳遞值的時候須要傳遞地址 // 第二個參數: 須要給指定方法的第幾個參數傳值 NSString *number = @"10086"; // 注意: 設置參數的索引時不能從0開始, 由於0已經被self佔用, 1已經被_cmd佔用 [invocation setArgument:&number atIndex:2]; NSString *content = @"love"; [invocation setArgument:&content atIndex:3]; NSString *status = @"success"; [invocation setArgument:&status atIndex:4]; // 2.調用NSInvocation對象的invoke方法 // 只要調用invocation的invoke方法, 就表明須要執行 \ NSInvocation對象中指定對象的指定方法, 而且傳遞指定的參數 [invocation invoke];
5、invocation封裝
這分類用於實現多個參數的方法
#import "NSObject+performSelector.h" @implementation NSObject (performSelector) - (id)performSelector:(SEL)aSelector withObjects:(NSArray *)objects { // 1.建立簽名對象 NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:aSelector]; // 判斷傳入的方法是否存儲, 若是方法不存在簽名對象爲nil if (signature == nil) { // 傳入的方法不存在 NSString *info = [NSString stringWithFormat:@" -[%@ %@]: unrecognized selector sent to instance", [self class], NSStringFromSelector(aSelector)]; // 拋異常 @throw [[NSException alloc] initWithName:@"一個牛B的錯誤" reason:info userInfo:nil]; } // 2.建立一個NSInvocation對象 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; // 3.保存方法所屬的對象 invocation.target = self; // 給invocation設置的方法, 必須和簽名中的方法一致 // 4.保存方法名稱 invocation.selector = aSelector; // 5.設置參數 /* 當前若是直接遍歷參數數組來設置參數, 會存在問題 若是參數數組元素多餘參數個數, 那麼就會報錯 */ NSUInteger arguments = signature.numberOfArguments - 2; /* 若是直接遍歷參數值的個數, 會存在問題 若是參數的個數大於了參數值的個數, 那麼數組會越界 */ NSUInteger objectsCount = objects.count; /* 參數和參數值, 誰少就遍歷誰 */ NSUInteger count = MIN(arguments, objectsCount); for (int i = 0; i < count; i++) { NSObject *obj = objects[i]; // 處理數組參數中NSNull問題 if ([obj isKindOfClass:[NSNull class]]) { obj = nil; } [invocation setArgument:&obj atIndex:i + 2]; } // 6.調用NSInvocation對象的invoke方法 [invocation invoke]; id res = nil; // 判斷當前方法是否有返回值 // NSLog(@"ReturnType = %zd", signature.methodReturnLength); if ( signature.methodReturnLength != 0) { // 7.獲取返回值 // getReturnValue方法會將會去到的方法返回值賦值給傳入的對象 [invocation getReturnValue:&res]; } return res; } @end
若要給參數傳空值
[self performSelector:@selector(sendMessageWithNumber:andContent:) withObjects:@[[NSNull null], @"love"]];
一、OC中調用JavaScipt
如何在OC中調用JavaScript代碼
使用UIWebView的stringByEvaluatingJavaScriptFromString方法便可
// [self.webView stringByEvaluatingJavaScriptFromString:@"showTitle();"];
二、JavaScipt中調用OC方法
好比要在這個網頁中調用oc的方法
<html> <!--描述網頁信息--> <head> <meta charset="UTF-8"/> <title>hello world</title> <script> function show() { alert(1); } function showTitle() { alert(document.title); } function repost() { location.href = "http://www.520it.com"; } function sum() { return 1 + 1; } function btnClick() { location.href = "xmg://sendMessageWithNumber_andContent_?10086&love"; } </script> </head> <!--網頁具體內容--> <body> 電話號碼: 13554499311</br> 郵箱: 97606813@qq.com</br> <button style = "background: red; height: 150px; width: 150px;" onclick = "btnClick();">哥是按鈕</button> </body> </html>
注意看function btnClick()這個方法
固定格式:
//後面跟的是方法名和參數
:用_代替
方法名和參數之間用?隔開
每一個參數之間用&隔開
好比說如今有這四個oc方法
- (void)call { NSLog(@"%s", __func__); } // callWithNumber: - (void)callWithNumber:(NSString *)number { NSLog(@"打電話給%@", number); } //sendMessageWithNumber:andContent: - (void)sendMessageWithNumber:(NSString *)number andContent:(NSString *)content { NSLog(@"發信息給%@, 內容是%@", number, content); } - (void)sendMessageWithNumber:(NSString *)number andContent:(NSString *)content status:(NSString *)status { NSLog(@"發信息給%@, 內容是%@, 發送的狀態是%@", number, content, status); }
要在JS跳轉網頁,實現下面這個代理方法
// 每次發送請求前都會調用
// 利用該方法做爲JS和OC之間的橋樑
// 在OC代理方法中經過判斷自定義協議頭, 決定是不是JS調用OC方法
// 在OC代理方法中經過截取字符串, 獲取JS想調用的OC方法名稱
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
沒有參數的狀況(消除異常)
NSString *schem = @"xmg://"; NSString *urlStr = request.URL.absoluteString; if ([urlStr hasPrefix:schem]) { NSLog(@"須要調用OC方法"); // 1.從URL中獲取方法名稱 // xmg://call NSString *methodName = [urlStr substringFromIndex:schem.length]; NSLog(@"%@", methodName); // 2.調用方法 SEL sel = NSSelectorFromString(methodName); // 忽略警告信息的做用範圍開始 #pragma clang diagnostic push // 下面這一行代碼是用於指定須要忽略的警告信息 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [self performSelector:sel withObject:nil]; // 忽略警告信息的做用範圍結束 #pragma clang diagnostic pop return NO; }
一個參數的狀況
NSString *schem = @"xmg://"; NSString *urlStr = request.URL.absoluteString; if ([urlStr hasPrefix:schem]) { NSLog(@"須要調用OC方法"); // 1.從URL中獲取方法名稱 // xmg://callWithNumber_?10086 NSString *subPath = [urlStr substringFromIndex:schem.length]; // 注意: 若是指定的用於切割的字符串不存在, 那麼就會返回整個字符串 NSArray *subPaths = [subPath componentsSeparatedByString:@"?"]; // 2.獲取方法名稱 NSString *methodName = [subPaths firstObject]; methodName = [methodName stringByReplacingOccurrencesOfString:@"_" withString:@":"]; NSLog(@"%@", methodName); // 2.調用方法 SEL sel = NSSelectorFromString(methodName); NSString *parmas = nil; if (subPaths.count == 2) { parmas = [subPaths lastObject]; } [self performSelector:sel withObject:parmas]; return NO;
兩個參數的狀況
NSString *schem = @"xmg://"; NSString *urlStr = request.URL.absoluteString; if ([urlStr hasPrefix:schem]) { NSLog(@"須要調用OC方法"); // 1.從URL中獲取方法名稱 // xmg://sendMessageWithNumber_andContent_?10086&love NSString *subPath = [urlStr substringFromIndex:schem.length]; // 注意: 若是指定的用於切割的字符串不存在, 那麼就會返回整個字符串 NSArray *subPaths = [subPath componentsSeparatedByString:@"?"]; // 2.獲取方法名稱 NSString *methodName = [subPaths firstObject]; methodName = [methodName stringByReplacingOccurrencesOfString:@"_" withString:@":"]; NSLog(@"%@", methodName); // 2.調用方法 SEL sel = NSSelectorFromString(methodName); // 3.處理參數 NSString *parma = nil; if (subPaths.count == 2) { parma = [subPaths lastObject]; // 3.截取參數 NSArray *parmas = [parma componentsSeparatedByString:@"&"]; [self performSelector:sel withObject:[parmas firstObject] withObject:[parmas lastObject]]; return NO; } [self performSelector:sel withObject:parma]; return NO; }
三個參數的狀況
// xmg:// NSString *schem = @"xmg://"; NSString *urlStr = request.URL.absoluteString; if ([urlStr hasPrefix:schem]) { NSLog(@"須要調用OC方法"); // 1.從URL中獲取方法名稱 // sendMessageWithNumber_andContent_?10086&love NSString *subPath = [urlStr substringFromIndex:schem.length]; // 注意: 若是指定的用於切割的字符串不存在, 那麼就會返回整個字符串 // sendMessageWithNumber_andContent_ // 10086&love NSArray *subPaths = [subPath componentsSeparatedByString:@"?"]; // 2.獲取方法名稱 NSString *methodName = [subPaths firstObject]; methodName = [methodName stringByReplacingOccurrencesOfString:@"_" withString:@":"]; NSLog(@"%@", methodName); // 2.調用方法 SEL sel = NSSelectorFromString(methodName); // 3.處理參數 NSArray *parmas = nil; if (subPaths.count == 2) { parmas = [[subPaths lastObject] componentsSeparatedByString:@"&"]; } [self performSelector:sel withObjects:parmas]; return NO; } return YES;