一、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;