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里面的数据,下次进入免去了下载的过 程。这在三行代码

的方法是完全行不通的。

目录
相关文章
|
10月前
|
存储 人工智能
软件设计师---钉子户5
软件设计师---钉子户5
87 0
|
10月前
|
自然语言处理 程序员 测试技术
软件设计师---钉子户3
软件设计师---钉子户3
79 0
|
10月前
|
存储 设计模式 算法
软件设计师---钉子户1
软件设计师---钉子户
67 0
|
10月前
|
存储 网络协议 安全
软件设计师---钉子户2
软件设计师---钉子户2
71 0
|
10月前
|
存储 机器学习/深度学习 数据安全/隐私保护
软件设计师---钉子户4
软件设计师---钉子户4
711 0
软件设计师---钉子户4
|
算法
算法题每日一练---第32天:奇怪的分式
上小学的时候,小明经常自己发明新算法。
152 0
算法题每日一练---第32天:奇怪的分式
|
程序员 Linux Windows
|
算法 程序员 C语言
从高考到程序员---一个五年程序员的回忆及建议
(本文参加CSDN的“从高考到程序员”征文活动,谢谢!) 每年的六月初,有关高考的信息就会见诸于报纸、网络等,让我这位多年之前参加高考的、已工作多年的人不由得也回忆起了自己高考时的情景。
1679 0
|
前端开发
逢年过节,这才是IT男向亲人朋友解释自己工作的正确姿势
逢年过节,如何向你的七大姑八大姨解释自己的工作就成了IT男最头疼问题,怎么和亲戚们介绍你的工作,才能不被“请”去修电脑、重装系统或者清理垃圾呢?本文就给IT男们提供应对七大姑八大姨们询问职业的正确回答姿势。
3857 0
|
SQL Java mybatis
奇怪的报错---待解决
### Error updating database. Cause: java.sql.SQLException: No operations allowed after statement closed.
1894 0