一、UIWebView简介


1、UIWebView
什么是UIWebView
UIWebView是iOS内置的浏览器控件
系统自带的Safari浏览器就是通过UIWebView实现的

UIWebView不但能加载远程的网页资源,还能加载绝大部分的常见文件
html\htm
pdf、doc、ppt、txt
mp4
… …

UIWebView常用的加载资源的方法
- (void)loadRequest:(NSURLRequest *)request;

2、键盘工具条显示中文

二、常用属性和方法


重新加载(刷新)
- (void)reload;

停止加载
- (void)stopLoading;

回退
- (void)goBack;

前进
- (void)goForward;

需要进行检测的数据类型
@property(nonatomic) UIDataDetectorTypes dataDetectorTypes

是否能回退
@property(nonatomic,readonly,getter=canGoBack) BOOL canGoBack;

是否能前进
@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;

四、NSInvocation,NSMethodSignature(签名)

//    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 = @"";
// 注意: 设置参数的索引时不能从0开始, 因为0已经被self占用, 1已经被_cmd占用
[invocation setArgument:&number atIndex:]; NSString *content = @"love";
[invocation setArgument:&content atIndex:]; NSString *status = @"success";
[invocation setArgument:&status atIndex:]; // 2.调用NSInvocation对象的invoke方法
// 只要调用invocation的invoke方法, 就代表需要执行 \
NSInvocation对象中指定对象的指定方法, 并且传递指定的参数
[invocation invoke];

五、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 - ;
/*
如果直接遍历参数值的个数, 会存在问题
如果参数的个数大于了参数值的个数, 那么数组会越界
*/
NSUInteger objectsCount = objects.count;
/*
参数和参数值, 谁少就遍历谁
*/
NSUInteger count = MIN(arguments, objectsCount); for (int i = ; i < count; i++) {
NSObject *obj = objects[i];
// 处理数组参数中NSNull问题
if ([obj isKindOfClass:[NSNull class]]) {
obj = nil;
}
[invocation setArgument:&obj atIndex:i + ];
} // 6.调用NSInvocation对象的invoke方法
[invocation invoke]; id res = nil;
// 判断当前方法是否有返回值
// NSLog(@"ReturnType = %zd", signature.methodReturnLength);
if ( signature.methodReturnLength != ) {
// 7.获取返回值
// getReturnValue方法会将会去到的方法返回值赋值给传入的对象
[invocation getReturnValue:&res];
} return res;
}
@end

若要给参数传空值

[self performSelector:@selector(sendMessageWithNumber:andContent:) withObjects:@[[NSNull null], @"love"]];

六、JavaScript


1、OC中调用JavaScipt
如何在OC中调用JavaScript代码
使用UIWebView的stringByEvaluatingJavaScriptFromString方法即可

// [self.webView stringByEvaluatingJavaScriptFromString:@"showTitle();"];

2、JavaScipt中调用OC方法

比如要在这个网页中调用oc的方法

<html>
<!--描述网页信息-->
<head>
<meta charset="UTF-8"/>
<title>hello world</title>
<script>
function show()
{
alert();
} function showTitle()
{
alert(document.title);
} function repost()
{
location.href = "http://www.520it.com";
}
function sum()
{
return + ;
} function btnClick()
{
location.href = "xmg://sendMessageWithNumber_andContent_?10086&love";
}
</script>
</head>
<!--网页具体内容-->
<body>
电话号码: </br>
邮箱: @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 == ) {
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 == ) {
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 == ) {
parmas = [[subPaths lastObject] componentsSeparatedByString:@"&"];
}
[self performSelector:sel withObjects:parmas];
return NO;
} return YES;

iOS开发——网络篇——UIWebview基本使用,NSInvocation(封装类),NSMethodSignature(签名),JavaScript,抛异常,消除警告的更多相关文章

  1. iOS开发网络篇—数据缓存

      iOS开发网络篇—数据缓存 一.关于同一个URL的多次请求 有时候,对同一个URL请求多次,返回的数据可能都是一样的,比如服务器上的某张图片,无论下载多少次,返回的数据都是一样的. 上面的情况会造 ...

  2. iOS开发网络篇—监测网络状态(转)

    文章转载自:http://www.cnblogs.com/wendingding/p/3950114.html iOS开发网络篇—监测网络状态 一.说明 在网络应用中,需要对用户设备的网络状态进行实时 ...

  3. iOS开发网络篇—大文件的多线程断点下载

    http://www.cnblogs.com/wendingding/p/3947550.html iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时 ...

  4. iOS开发网络篇—简单介绍ASI框架的使用

    iOS开发网络篇—简单介绍ASI框架的使用 说明:本文主要介绍网络编程中常用框架ASI的简单使用. 一.ASI简单介绍 ASI:全称是ASIHTTPRequest,外号“HTTP终结者”,功能十分强大 ...

  5. iOS开发网络篇—网络编程基础

    iOS开发网络篇—网络编程基础 一.为什么要学习网络编程 1.简单说明 在移动互联网时代,移动应用的特征有: (1)几乎所有应用都需要用到网络,比如QQ.微博.网易新闻.优酷.百度地图 (2)只有通过 ...

  6. iOS开发网络篇—搭建本地服务器

    iOS开发网络篇—搭建本地服务器 一.简单说明 说明:提前下载好相关软件,且安装目录最好安装在全英文路径下.如果路径有中文名,那么可能会出现一些莫名其妙的问题. 提示:提前准备好的软件 apache- ...

  7. iOS开发网络篇—HTTP协议

    iOS开发网络篇—HTTP协议 说明:apache tomcat服务器必须占用8080端口 一.URL 1.基本介绍 URL的全称是Uniform Resource Locator(统一资源定位符) ...

  8. iOS开发网络篇—NSURLConnection基本使用

    iOS开发网络篇—NSURLConnection基本使用 一.NSURLConnection的常用类 (1)NSURL:请求地址 (2)NSURLRequest:封装一个请求,保存发给服务器的全部数据 ...

  9. iOS开发网络篇—GET请求和POST请求

    iOS开发网络篇—GET请求和POST请求 一.GET请求和POST请求简单说明 创建GET请求 // 1.设置请求路径 NSString *urlStr=[NSString stringWithFo ...

随机推荐

  1. 日期String相互转换

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");Date endate = sdf.parse(endDate) ...

  2. tomcat7.0配置CORS(跨域资源共享)

    平时我们做前台页面时可能会遇到浏览器以下提示(浏览器控制台): 已阻止跨源请求:同源策略禁止读取位于 http://xxx.xxx.com 的远程资源.(原因:CORS 头缺少 'Access-Con ...

  3. 关于datatable linq的转换

    关于datatable datarow DataTable paraval = GetParaVal(DateCondition, strUrl, Page, RowPage, iYearMonthN ...

  4. maven学习讲解

    参考链接:http://www.cnblogs.com/bigtall/archive/2011/03/23/1993253.html 1.前言 Maven,发音是[`meivin],"专家 ...

  5. Java 命令行运行参数大全

    Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOME"bin"java –option 来启动,-option为虚拟 ...

  6. php-fpm服务挂掉

    今天发了个链接,可能同时在线的人瞬间比较多,结果网站报503错误,回去打开php-fpm错误日志一看,php-fpm服务挂掉了,报如下错误: [04-Apr-2016 15:38:04] NOTICE ...

  7. 11 Clever Methods of Overfitting and how to avoid them

    11 Clever Methods of Overfitting and how to avoid them Overfitting is the bane of Data Science in th ...

  8. 解惑好文:移动端H5页面高清多屏适配方案 (转)

    转自:http://mobile.51cto.com/web-484304.htm https://github.com/amfe/lib-flexible/blob/master/src/makeg ...

  9. Nginx限制某个IP同一时间段的访问次数

    nginx可以通过HttpLimitReqModul和HttpLimitZoneModule配置来限制ip在同一时间段的访问次数. HttpLimitReqModul用来限制连单位时间内连接数的模块, ...

  10. CMD窗口如何调整大小 / 颜色

    Windows默认的命令行工具CMD暴丑无比..很多人都会因为这个原因去寻找漂亮的命令行工具.. 但是很多所谓的命令行工具并不能完美的支持到CMD.. 譬如 PowerCMD 或 Cmder 之流.. ...