iOS缓存方案
2016-01-11 17:21
459 查看
App已经与我们形影不离了,不管在地铁上、公交上还是在会场你总能看到很多人拿出来手机,刷一刷微博,看看新闻。
据不完全统计有近一半的用户在非Wifi环境打开App,以下为一个典型iPhone和AndroidApp(50W+用户)的友盟后台数据:
3G、2G的数据连接往往不稳定(特别在公交或者地铁上),这时打开一些App就会像这样:
当然也会有一些体验很好的App,在离线状态下也能顺畅使用:
甚至提供了离线阅读功能:
如何做?
打开过的文章、下载过的音频、查看过的图片我们都希望Cache到本地,下次不用再向服务器请求。
首先,我们为了最快让用户看到内容,会在ViewDidLoad加载Cache数据,如:
?
然后在viewDidAppear中向服务器请求最新数据,如
?
当然这里的getArticleList接口有useCacheFirst参数,我们需要网络请求模块能够支持这一点,下面就介绍这些库和工具。(借助一些工具很容易能做到这些,而不用自己造轮子。遵循“凡事都应该最简单,而不过于简陋”的原则,这里整理一下,方便项目中使用)。
Sample(参考麒麟的文章《iOS开发之缓存(一):内存缓存》来使用NSURLCache):
?
但是NSMutableURLRequest使用起来不够简便,在实际项目中我很少用它,而基本使用ASIHTTPRequest来代替。
你可以从这里找到它的介绍:http://allseeing-i.com/ASIHTTPRequest/,在5.0/4.0及之前iOS版本,ASIHTTPRequest基本是主力的
HTTPrequestslibrary,它本身也是Github中的开源项目,但是从iOS5.0之后逐渐停止维护了。未来的项目可以使用AFNetworking 或者MKNetworkKit 代替ASIHTTPRequest。
ASIHTTPRequest的简介如下:
ASIHTTPRequestisaneasytousewrapperaroundtheCFNetworkAPIthatmakessomeofthemoretediousaspectsofcommunicatingwithwebserverseasier.ItiswritteninObjective-CandworksinbothMacOSXandiPhoneapplications.
ItissuitableperformingbasicHTTPrequestsandinteractingwithREST-basedservices(GET/POST/PUT/DELETE).TheincludedASIFormDataRequestsubclassmakesiteasytosubmitPOSTdataandfilesusingmultipart/form-data.
ASIHTTPRequest库API设计的简单易用,并且支持block、queue、gzip等丰富的功能,这是该开源项目如此受欢迎的主要原因。
ASIHTTPRequest库中提供了ASIWebPageRequest组件用于请求网页,并且能把网页中的外部资源一并请求下来,但是我在实际项目中使用后发现有严重Bug,所以不建议使用。
ASIHTTPRequest库的介绍中也提到了它可以支持REST-basedservice,但是与RestfullAPI打交道我们往往使用下面介绍的的RestKit。
Sample:
?
官方网站:http://restkit.org/,Github开源项目,与RestfullAPI的Web服务打交道,这个库非常便捷,它也提供了很完整的Cache机制。
Sample:
?
?
Cache请求只是RestKit最基本的功能,RestKit真正强大的地方在于处理与RESTfulwebservices交互时的相关工作非常简便(https://github.com/RestKit/RestKit/wiki),RestKit还可以Cache
datamodel到CoreData中:
CoreDatasupport.Buildingontopoftheobjectmappinglayer,RestKitprovidesintegrationwithApple'sCoreDataframework.ThissupportallowsRestKittopersistremotelyloadedobjectsdirectlybackintoalocalstore,eitherasafastlocalcacheor
aprimarydatastorethatisperiodicallysyncedwiththecloud.RestKitcanpopulateCoreDataassociationsforyou,allowingnaturalpropertybasedtraversalofyourdatamodel.ItalsoprovidesaniceAPIontopoftheCoreDataprimitivesthatsimplifies
configurationandqueryingusecasesthroughanimplementationoftheActiveRecordaccesspattern.
但实际上RKRequestCachePolicy已经解决了大部分Cache需求。
SDWebImage是Github开源项目:https://github.com/rs/SDWebImage,它用于方便的请求、Cache网络图片,并且请求完毕后交由UIImageView显示。
AsynchronousimagedownloaderwithcachesupportwithanUIImageViewcategory.
SDWebImage作为UIImageView的一个Category提供的,所以使用起来非常简单:
?
AFNetworking也提供了类似功能(UIImageView+AFNetworking):
?
如果你使用UIWebView来展示内容,在离线情况下如果也想能显示的话需要实现2点:
CacheHtml页面
Cache图片等元素
使用上面介绍的网络组件来CacheHtml页面比较便捷,之后使用webViewloadHTMLString即可加载本地Html页面,而Cache图片需要更换NSURLCache公共实例为自定义的NSURLCache(UIWebView使用的即是+[NSURLCachesharedURLCache]):
?
自定义NSURLCache:
?
详细的见NewsReader中的LocalSubstitutionCache.h/.m和WebViewController.m中的viewDidLoad,News
Reader开源项目这里参考的是:http://cocoawithlove.com/2010/09/substituting-local-data-for-remote.html
在没有网络的情况下使用已经Cache过的所有数据:文章、图片、音频等等,用到的主要方案已经在上面介绍了,详细的请看源码:https://github.com/cubewang/NewsReader。
NewsReader项目因为历史演进的原因已经有些庞大了,需要进一步重构,在之后的项目中我们的客户端结构更精简。
据不完全统计有近一半的用户在非Wifi环境打开App,以下为一个典型iPhone和AndroidApp(50W+用户)的友盟后台数据:
3G、2G的数据连接往往不稳定(特别在公交或者地铁上),这时打开一些App就会像这样:
当然也会有一些体验很好的App,在离线状态下也能顺畅使用:
甚至提供了离线阅读功能:
如何做?
打开过的文章、下载过的音频、查看过的图片我们都希望Cache到本地,下次不用再向服务器请求。
首先,我们为了最快让用户看到内容,会在ViewDidLoad加载Cache数据,如:
1 2 3 4 | - ( void )viewDidLoad { [self getArticleList:0length:SECTION_LENGTHuseCacheFirst:YES]; } |
1 2 3 4 5 6 7 8 | - ( void )viewDidAppear:( BOOL )animated { [super viewDidAppear:animated]; //... [self getArticleList:0length:SECTION_LENGTHuseCacheFirst:NO] } |
1.NSMutableURLRequest
Sample(参考麒麟的文章《1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | NSString *paramURLAsString=@ " ; if ([paramURLAsString length]==0){ NSLog(@ "Nil oremptyURLisgiven" ); return ; } NSURLCache *urlCache=[NSURLCachesharedURLCache]; /* 设置缓存的大小为1M*/ [urlCache setMemoryCapacity:1*1024*1024]; //创建一个nsurl NSURL //创建一个请求 NSMutableURLRequest [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0f]; //从请求中获取缓存输出 NSCachedURLResponse [urlCache cachedResponseForRequest:request]; //判断是否有缓存 if (response NSLog(@ "如果有缓存输出,从缓存中获取数据" ); [request setCachePolicy:NSURLRequestReturnCacheDataDontLoad]; } self.connection /* 创建NSURLConnection*/ NSURLConnection [[NSURLConnection delegate:self startImmediately:YES]; self.connection [newConnection release]; |
2.ASIHTTPRequest
你可以从这里找到它的介绍:HTTPrequestslibrary,它本身也是Github中的开源项目,但是从iOS5.0之后逐渐停止维护了。未来的项目可以使用
ASIHTTPRequest的简介如下:
ASIHTTPRequestisaneasytousewrapperaroundtheCFNetworkAPIthatmakessomeofthemoretediousaspectsofcommunicatingwithwebserverseasier.ItiswritteninObjective-CandworksinbothMacOSXandiPhoneapplications.
ItissuitableperformingbasicHTTPrequestsandinteractingwithREST-basedservices(GET/POST/PUT/DELETE).TheincludedASIFormDataRequestsubclassmakesiteasytosubmitPOSTdataandfilesusing
ASIHTTPRequest库API设计的简单易用,并且支持block、queue、gzip等丰富的功能,这是该开源项目如此受欢迎的主要原因。
ASIHTTPRequest库中提供了ASIWebPageRequest组件用于请求网页,并且能把网页中的外部资源一并请求下来,但是我在实际项目中使用后发现有严重Bug,所以不建议使用。
ASIHTTPRequest库的介绍中也提到了它可以支持REST-basedservice,但是与RestfullAPI打交道我们往往使用下面介绍的的RestKit。
Sample:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | NSMutableString //如果优先使用本地数据 ASICachePolicy : asiRequest [NSURL [asiRequest [asiRequest setCachePolicy:policy]; [asiRequest setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy]; // Connection if (_connectionType [asiRequest setDelegate:self]; [asiRequest startAsynchronous]; // if (!_canceled [_delegate downloaderDidStart:self]; } else { [asiRequest startSynchronous]; NSError if (!error) { [self requestFinished:asiRequest]; } else { [self requestFailed:asiRequest]; } } [requestedUrl release]; |
3.RestKit
官方网站:Sample:
1 2 3 4 5 6 7 8 9 10 11 12 | + ( void )setCachePolicy:( BOOL )useCacheFirst { RKObjectManager* if (useCacheFirst) { objectManager.client.cachePolicy //使用本地Cache,如果没有Cache请求服务器 } else { objectManager.client.cachePolicy //离线或者超时时使用本地Cache } } |
1 2 3 4 5 6 7 8 9 10 11 12 | + ( BOOL )getHomeTimeline:(NSInteger)maxId length:(NSInteger)length delegate:(id<RKObjectLoaderDelegate>)delegate useCacheFirst:( BOOL )useCacheFirst { if (delegate return NO; [iKnowAPI setCachePolicy:useCacheFirst]; //... } |
datamodel到CoreData中:
CoreDatasupport.Buildingontopoftheobjectmappinglayer,RestKitprovidesintegrationwithApple'sCoreDataframework.ThissupportallowsRestKittopersistremotelyloadedobjectsdirectlybackintoalocalstore,eitherasafastlocalcacheor
aprimarydatastorethatisperiodicallysyncedwiththecloud.RestKitcanpopulateCoreDataassociationsforyou,allowingnaturalpropertybasedtraversalofyourdatamodel.ItalsoprovidesaniceAPIontopoftheCoreDataprimitivesthatsimplifies
configurationandqueryingusecasesthroughanimplementationoftheActiveRecordaccesspattern.
但实际上RKRequestCachePolicy已经解决了大部分Cache需求。
4.SDWebImage
SDWebImage是Github开源项目:AsynchronousimagedownloaderwithcachesupportwithanUIImageViewcategory.
SDWebImage作为UIImageView的一个Category提供的,所以使用起来非常简单:
1 2 3 | // [imageView " ] placeholderImage:[UIImage imageNamed:@ "placeholder.png" ]]; |
1 2 | UIImageView [imageView " ] "placeholder-avatar" ]]; |
5.UIWebView中的图片Cache
如果你使用UIWebView来展示内容,在离线情况下如果也想能显示的话需要实现2点:CacheHtml页面
Cache图片等元素
使用上面介绍的网络组件来CacheHtml页面比较便捷,之后使用webViewloadHTMLString即可加载本地Html页面,而Cache图片需要更换NSURLCache公共实例为自定义的NSURLCache(UIWebView使用的即是+[NSURLCachesharedURLCache]):
1 2 3 4 5 | //设置使用自定义Cache机制 LocalSubstitutionCache [cache [cache [NSURLCache setSharedURLCache:cache]; |
1 2 3 4 5 6 7 8 9 10 | #import <Foundation/Foundation.h> @interface { NSMutableDictionary *cachedResponses; } + (NSString*)pathForURL:(NSURL*)url; @end |
Reader开源项目这里参考的是:
NewsReader中的介绍
《iOSNewsReader开源项目》这篇文章介绍到的开源项目改进了离线使用体验:
在没有网络的情况下使用已经Cache过的所有数据:文章、图片、音频等等,用到的主要方案已经在上面介绍了,详细的请看源码:
NewsReader项目因为历史演进的原因已经有些庞大了,需要进一步重构,在之后的项目中我们的客户端结构更精简。
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- 浅析SQL Server中的执行计划缓存(上)
- Enterprise Library for .NET Framework 2.0缓存使用实例
- PowerShell中编程清空IE缓存方法
- PowerShell中使用.NET将程序集加入全局程序集缓存
- C#中缓存的基本用法总结
- wap开发中如何有效的利用缓存减少消息的传送量
- PHP基于文件存储实现缓存的方法
- smarty缓存用法分析
- 引用全局程序集缓存内的程序集的方法
- asp Response.flush 实时显示进度
- C#实现清除IE浏览器缓存的方法
- ASP.NET缓存管理的几种方法
- PHP文件缓存类实现代码