开发者社区> 李牙刷儿> 正文

Objective-c下具有下载功能的NSURLCache类CustomURLCache

简介: 最近在做iOS APP开发的过程中遇到了这么一个问题:我开发的是一个阅读类的App,正文界面是通过UIWebViewController来实现的,现在要实现文章离线阅读功能。即将当前web页面所有的资源请求结果都下载都本地。在网上找了很多方法,发现都不是很好。后来还是决定从cache入手:iOS自带的NSURLCache并不支持将cache下载到自定义的目录底下,所以只有复写NSURL
+关注继续查看

最近在做iOS APP开发的过程中遇到了这么一个问题:我开发的是一个阅读类的App,正文界面是通过UIWebViewController来实现的,现在要实现文章离线阅读功能。即将当前web页面所有的资源请求结果都下载都本地。在网上找了很多方法,发现都不是很好。后来还是决定从cache入手:iOS自带的NSURLCache并不支持将cache下载到自定义的目录底下,所以只有复写NSURLCache这个类来实现这些功能。在网上找到一个他人写的CustomURLCache的类,但是发现使用的过程中程序会崩,于是一步一步调试代码,定位到该类的错误,对代码进行了修改,修复了这个bug。而随着iOS8的推出,发现设置自定义的URLCache必须要在AppDelegate.m的 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 函数中使用才行,否则无效。无奈,只好进一步对代码进行修改。终于可以适配ios8了。今天将这部分代码分享出来,希望对大家有用。代码我已经托管到github上,大家可以自行下载。

同时为了兼容系统NSURLCache的功能,CustomURLCache有两种模式,NORMAL_MODE和DOWNLOAD_MODE,NORMALMODE下的CustomCache和NSURLCache的功能是一样的;而DOWNLOADMODE下的CustomURLCache则可以实现包含自定义下载目录,设置过期时间的子功能的下载功能。

接下来用例子教大家如何使用CustomURLCache这个类。假设我们在做一个阅读类的App,正文页面用UIWebViewController来展示。现在需要实现一个离线下载的功能,即将当前网页的所有访问到的资源(html文件,图片,JavaScript,CSS等等)全部都保存到本地。用CustomURLCache就可以很容易地实现这个功能。

在AppDelegate.m中将CustomURLCache设置为全局URLCache

上文已经讲到了,在iOS8中,设置全局URLCache必须在AppDelegate.m中的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions实现,所以第一步就是将我们CustomURLCache在该函数中设置为全局URLCache:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    ......
    //Init custom cache
    
    CustomURLCache *_mCache = [[CustomURLCache alloc] initWithMemoryCapacity:20 * 1024 * 1024
                                                diskCapacity:200 * 1024 * 1024
                                                    diskPath:nil
                                                   cacheTime:0
                                                subDirectory:nil];
    [NSURLCache setSharedURLCache:_mCache];

    return YES;
}

这段代码将我们的CustomURLCache设置为了全局的URLCache,其中的参数有如下意义:

  • diskCapacity:就是用户设置的这个cache的大小
  • diskPath:cache的下载路径,如果设置为nil的话,那么该类将会自动将当前应用的缓存目录作为下载路径
  • cacheTime:cache的过期时间,如果设置为0的话,那么cache将永远不会过期
  • subDirectory:这是位于diskPath下的子目录,意为当前的cache会存在哪个子目录中。不过在初始化的时候只用将其设置为nil即可

值得说明的时候,在初始化之后其实没有任何变化,因为这个时候的默认模式是NORMAL_MODE,即跟NSURLCache是一样的。所以感觉不出什么不一样。不要着急,很快我们就需要使用到DOWNLOAD_MODE了。

将CustomURLCache设置为DOWNLOAD_MODE

好了,假设我们在第一个页面选中了一篇文章,然后点击计入了正文页面,正文页面的布局很简单,就是一个UIWebView,我们需要用其显示一个网页,并且将所有需要请求的资源都下载到本地自定义的目录中。这个时候就需要用到DOWNLOAD_MODE了。实现很简单,在正文界面的UIViewController的- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil或者init函数中将CustomURLCache设置为DOWNLOAD_MODE:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        
        ......

    
        _mCache = (CustomURLCache *)[NSURLCache sharedURLCache];
        [_mCache changeToDownloadMode:_subDir];
        [NSURLCache setSharedURLCache:_mCache];
    }
    return self;
}

现在我们就成功地将CustomURLCache设置为了下载模式,在执行[_mCache changeToDownloadMode:_subDir];时需要指定下载子目录,就位于diskPath下的下载子目录。接下来所有的web请求资源都会下载到我们的自定义目录了。

将CustomURLCache恢复到NORMAL_MODE

好了,现在web页面也展现出来了,所有的web请求资源都下载到本地了,该退出了。回退到第一个页面,并且不再需要DOWNLOAD_MODE,我们要将其恢复为NORMAL_MODE,那么在当前UIViewController下的dealloc函数或者其他用户自定义的退出函数中加入如下代码(在这里我使用的是自己的退出函数):

- (void)backToMainpage:(id)sender {
    if (不再需要文章缓存) {
        NSLog(@"删除文章缓存");
        [_mCache removeCustomRequestDictionary ];  
    }
    else
    {
    //do nothing
     }
    //不再使用自定义缓存,而是换到系统的缓存
    [_mCache changeToNormalMode];
    [self.navigationController popViewControllerAnimated:YES];
}

好了,如果你没有删除文章缓存,那么当我们再次就如正文页面的时候,你会发现页面很快就加在完成了。原因很简单,当你再次进入该UIViewController的时候,程序又会执行[_mCache changeToDownloadMode:_subDir];这时,CustomURLCache在接到URL请求的时候会先到_subDir路径下去找是否有缓存的资源,如果找到了,并且还不过期,那么就会自动加在本地的资源,如果没有找到或者过期了,那么会重新通过网络请求。所以你知道为什么这么快就完成了,因为所有的资源都是在本地的!

好了,简单地使用就介绍到这里了。希望对大家有帮助。同时,如果大家喜欢的话就请在GitHub上fork或者star一下吧,万分感谢!地址是:点击打开链接

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
18058 0
AliOS Things技术底层加持cYoC物联网操作系统 获国际TUeV功能安全认证
近日,以阿里云物联网操作系统AliOS Things技术底层加持、平头哥半导体有限公司自主研发的YoC软件平台斩获了国际公认第三方认证机构SGS-TUeV SAAR颁发的SIL3功能安全证书。这标志着平头哥YoC软件平台,具备了与国际规范接轨的能力,也进一步体现了阿里云自产自研的AliOS Things系统底层的技术含量与端侧实力。
985 0
AliOS Things技术底层加持平头哥YoC物联网操作系统 获国际TUeV功能安全认证
近日,以阿里云物联网操作系统AliOS Things技术底层加持、平头哥半导体有限公司自主研发的YoC软件平台斩获了国际公认第三方认证机构SGS-TUeV SAAR颁发的SIL3功能安全证书。这标志着平头哥YoC软件平台,具备了与国际规范接轨的能力,也进一步体现了阿里云自产自研的AliOS Things系统底层的技术含量与端侧实力。
1051 0
【新功能发布】阿里云云解析DNS“子域名管理”功能上线
大家期待已久的云解析“子域名管理”新功能已于8月7日成功上线。子域名管理是阿里云针对用户对主、子域名分别管理的需求场景下,推出的全新功能。 我们先来看看两个基本概念。 子域名:例如 http://www.aliyun.com 是 http://aliyun.com 的子域名。
1039 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
23590 0
Unity 捏脸整理及基于骨骼的捏脸功能实现
目前实现捏脸功能的方式主要有两种。一个是Blendshape(融合变形),一个是基于骨骼驱动的方式,通过修改骨骼矩阵(bindpose)来影响SkinMesh。这两种方式的最终原理都是在shader 生效之前修改顶点。
2773 0
ActiveReports 9 新功能:借助目录(TOC)控件为报表添加目录功能
原文:ActiveReports 9 新功能:借助目录(TOC)控件为报表添加目录功能 在最新发布的ActiveReports 9报表控件中添加了多项新功能,以帮助你在更短的时间里创建外观绚丽、功能强大的报表系统,本文将重点介绍新增文档目录控件(TOC),通过拖拽操作便可添加报表目录。
1040 0
+关注
李牙刷儿
Android开发者&前端菜鸟,专注于跨平台、热修复领域
87
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载