iOSUIWebView---快停下啦,你的愚蠢的行为

简介:

公元前
之前还是学生时代的时候给社团们学弟学妹们介绍iOS编程的时候,简单的准备了图灵ios培训第一周(使用UIWebView创建简易浏览器)

NSURL *url =[NSURL URLWithString:urlString];

NSLog(urlString);

NSURLRequest *request =[NSURLRequest requestWithURL:url];

[webView loadRequest:request];

运用的就是上面的这种三行代码搞定一切的网页加载的方法。

公元后

后来在项目中遇到了使用UIWebView控件时,理所当然的愚蠢的

用了里面的方法完成了Boss的需求,但后期测试的时候,在肾4上

以及用Charles工具模拟慢网速的时候发现这样做的用户体验不太

好,主要的问题就是当该网页内容非常多的时候,在2G网络和移

动3G网络的时候,出现加载太慢,出现卡顿的现象。甚至在旧机

器上会出现崩溃的现象

分析一下原因,主要由以下几种原因:

1.旧的手机CPU性能内存较差,一下占用率太高。(PS:后来

iOS8之后苹果出了新的WebKit框架WKWebKit,性能提升了不

少,建议不需要适配iOS8以下的可以考虑尝试)

2.页面内容较多,数据量庞大,即使是新款手机也扛不住呀(最

典型的应该是天猫商城App的首页啦,下拉了几分钟还没有到达尽

头,一下子加载全部数据,手机肯定扛不住呀)
这里写图片描述

这里写图片描述
3. 运用上面那种人人都会的没技术含量的代码是在主线程里面进

行的,数据量大,网速不行,会一值在加载,影响用户进行其他

操作

那怎样解决上边的问题呢?

  1. 换手机?别逗了一个肾机依旧那么贵,NO Pass

  2. 加载页面的时候做上缓存,甚至分段的展示数据(先只加载一部分数据,随着用户下拉再逐步加载)

  3. 既然担心数据量多造成在主线程调用会卡死,那就想想办法另外开辟线程加载数据

权衡之后

上边的代码方法是万万行不通的最常用的还是想想办法另辟蹊径的开辟新航线:

这里我们可以用到常用多线程四种方法中的一种:

NSOperationQueue 操作队列中进行编程
1.创建一个队列并初始化:

static NSOperationQueue *queue;
queue=[[NSOperationQueue alloc]init];

2.创建操作对象并封装要执行的任务

 NSInvocationOperation *op=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downLoadWeb) object:nil];

将对象添加到队列中

 [queue addOperation:op];

3.开辟一个新的线程,实现执行的任务,获取从服务器上加载的数据,并存储在NSData中

 -(void)downLoadWeb
    {

NSURL *url=[NSURL URLWithString:@"http://·········.php"];

NSError *error;

NSString *strData=[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];

NSData *data=[strData dataUsingEncoding:NSUTF8StringEncoding];

if (data !=nil) {

    [self performSelectorOnMainThread:@selector(downLoad_completed:) withObject:data waitUntilDone:NO];

}
else
{
    NSLog(@"error when download:%@",error);

}
}

4.判断从服务器中正确的获得数据后,再返回主线程中进行数据的加载(为啥要返回主线程,因为苹果规定数据加载到控件上必须在主线程上进行,防止多个线程修改控件引发崩溃和莫名其妙的问题

-(void)downLoad_completed:(NSData *)data
{

NSURL *url=[NSURL URLWithString:@"http://·········.php"];
   NSString *nameType=[self mimeType:url];
NSLog(@"%@",nameType);

[webView loadData:data MIMEType:nameType textEncodingName:@"UTF-8" baseURL:url];
}

上面中用到了UIWebView的

loadData:<#(nonnull NSData *)#> MIMEType:<#(nonnull NSString *)#> textEncodingName:<#(nonnull NSString *)#> baseURL:<#(nonnull NSURL *)#>

//第一个诶参数是一个NSData
//第二个参数是MIMEType  
//第三个参数是编码格式  
//第四个相对地址。

其中第二参数需要调用一下下面方法,获取指定URL的MIMEType类型

 #pragma mark 获取指定URL的MIMEType类型  
- (NSString *)mimeType:(NSURL *)url  
{  

NSURLRequest *request = [NSURLRequest requestWithURL:url];  

   //使用同步方法后去MIMEType  
NSURLResponse *response = nil;  

[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];  

return response.MIMEType;  
} 

这里返回的是text/html

第四个参数是传的URL的地址,当时我尝试着赋值nil后发现网页里面的图片就不能正确的显示出来

好了,介绍好了步骤后反思一下为什么这么做比较好的用户体验

1.首先我们运用了多线程加载数据,不影响用户操作其他数据

我还故意调皮的在downLoadWeb中加上下面的代码:

for (int i=1; i<100000000; i++) {
    NSLog(@"我卡到你了吗?");
}

测试结果完全不影响用户操作其他地方,要是按原始的三行代

码搞定UIWebView就会出现一直卡的悲催体验。

2.我们先在子线程中把数据加载到NSData中,再 通过loadData:函

数进行加载,相当于进行了本地数据的读取操作,本地读取的速

度是远远大于网络获取的。

3.对于网页数据基本保持不变的,我们完全可以 用数据库存储

NSData里面的数据,下次进入免去了下载的过 程。这在三行代码

的方法是完全行不通的。

目录
相关文章
|
26天前
|
Rust Java
set 方法是坏味道?
【10月更文挑战第19天】
27 5
|
程序员
什么是好代码/坏代码?给普通人的图解示例
什么是好代码/坏代码?给普通人的图解示例
109 0
|
算法 Linux C语言
入职Linux驱动工程师后,我才知道的真相......
大家好,我是Vincent。做Linux驱动工程师也有一段时间了,今天分享一下我曾经入职才知道的一些事情,算是一个菜鸟的经历吧。
【perl】老司机的再一次翻车:没有想到加了一句打印,会影响结果输出
【perl】老司机的再一次翻车:没有想到加了一句打印,会影响结果输出
|
机器学习/深度学习 算法 编译器
明天省赛,我都还不太熟悉Dev - C++,怎么切换成C++11了?它的报错看不懂呀,那花八分钟看看这篇文章吧~解决你的困惑。
明天省赛,我都还不太熟悉Dev - C++,怎么切换成C++11了?它的报错看不懂呀,那花八分钟看看这篇文章吧~解决你的困惑。
1280 0
明天省赛,我都还不太熟悉Dev - C++,怎么切换成C++11了?它的报错看不懂呀,那花八分钟看看这篇文章吧~解决你的困惑。
|
Python
又烧脑又炫技还没什么用,在代码里面打印自身
又烧脑又炫技还没什么用,在代码里面打印自身
207 0
又烧脑又炫技还没什么用,在代码里面打印自身
|
设计模式 前端开发 JavaScript
那个一年前找不到工作的男人,2021年怎么样了?
那个一年前找不到工作的男人,2021年怎么样了?
|
算法
算法题每日一练---第32天:奇怪的分式
上小学的时候,小明经常自己发明新算法。
185 0
算法题每日一练---第32天:奇怪的分式
|
Java 应用服务中间件 程序员
一年了,请不要忘记这位枉死的天才程序员,以及......
不知大家是否还记得一年前的苏享茂事件。 苏享茂,一个出生在贫寒家庭的程序员,依靠自己在技术上的天赋和努力,逆袭成为WePhone 的创始人,坐拥千万身家。
1066 0