App Analytics in the App Store
The app has been inseparable from us, whether on the subway, bus or in the venue you can always see a lot of people come out of mobile phones, brush a micro bo, see the News.
Incomplete statistics of nearly half of the users in the non-WiFi environment to open the APP, the following is a typical iphone and Android app (50w+ users) of the league background data:
3G, 2G of data connection is often unstable (especially on the bus or metro), then open some apps will be like this:
Of course, there will be some very good apps that can be used smoothly offline:
It even provides offline reading capabilities:
How to do?
Open articles, downloaded audio, viewed images we all want the cache to be local, and the next time we don't have to ask the server.
First, we load the cache data in Viewdidload for the fastest user to see the content, such as:
1234 |
- ( void )viewDidLoad { [self getArticleList:0 length:SECTION_LENGTH useCacheFirst:YES]; } |
Then, in Viewdidappear, request the latest data from the server, such as
12345678 |
- ( void )viewDidAppear:( BOOL )animated { [super viewDidAppear:animated]; //... [self getArticleList:0 length:SECTION_LENGTH useCacheFirst:NO] } |
Of course here the Getarticlelist interface has the Usecachefirst parameter, we need the network request module to support this point, the following describes these libraries and tools. (with some tools it's easy to do this without having to build wheels yourself.) Follow the principle of "everything should be the simplest, but not too shabby", here to tidy up, easy to use in the project).
1.NSMutableURLRequest
Sample (refer to Kylin's article "iOS Development Cache (i): Memory Cache" to use Nsurlcache):
1234567891011121314151617181920212223242526272829303132 |
NSString *paramURLAsString= @
"http://www.baidu.com/"
;
if ([paramURLAsString length] == 0){
NSLog(@
"Nil or empty URL is given"
);
return
;
}
NSURLCache *urlCache = [NSURLCache sharedURLCache];
/* 设置缓存的大小为1M*/
[urlCache setMemoryCapacity:1*1024*1024];
//创建一个nsurl
NSURL *url = [NSURL URLWithString:paramURLAsString];
//创建一个请求
NSMutableURLRequest *request =
[NSMutableURLRequest
requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0f];
//从请求中获取缓存输出
NSCachedURLResponse *response =
[urlCache cachedResponseForRequest:request];
//判断是否有缓存
if (response != nil){
NSLog(@
"如果有缓存输出,从缓存中获取数据"
);
[request setCachePolicy:NSURLRequestReturnCacheDataDontLoad];
}
self.connection = nil;
/* 创建NSURLConnection*/
NSURLConnection *newConnection =
[[NSURLConnection alloc] initWithRequest:request
delegate:self
startImmediately:YES];
self.connection = newConnection;
[newConnection release];
|
But Nsmutableurlrequest is not easy to use, I seldom use it in actual projects, and basically use asihttprequest instead.
2.ASIHTTPRequest
You can find it here: http://allseeing-i.com/ASIHTTPRequest/, in 5.0/4.0 and before the iOS version, ASIHTTPRequest is basically the main source of the HTTP requests library, It is also an open source project in GitHub itself, but it is gradually discontinued after iOS 5.0. Future projects can use afnetworking or mknetworkkit instead of asihttprequest.
ASIHTTPRequest's introduction is as follows:
ASIHTTPRequest is a easy-to-use wrapper around the cfnetwork API that makes some of the more tedious aspects of Communica Ting with Web servers easier. It's written in Objective-c and works in both Mac OS X and IPhone applications.
It is suitable performing basic HTTP requests and interacting with rest-based services (get/post/put/delete). The included Asiformdatarequest subclass makes it easy to submit POST data and files Usingmultipart/form-data.
The ASIHTTPRequest Library API is designed to be easy to use and supports rich features such as block, queue, gzip, which is the main reason why the open source project is so popular.
The ASIHTTPRequest library provides the Asiwebpagerequest component for requesting a Web page, and can request the external resources in the Web page, but I found a serious bug in the actual project, so it is not recommended.
The ASIHTTPRequest library also mentions that it can support rest-based service, but we often use the restkit described below for dealing with Restfull APIs.
Sample:
12345678910111213141516171819202122232425262728293031323334353637383940 |
NSMutableString *requestedUrl = [[NSMutableString alloc] initWithString:self.url];
//如果优先使用本地数据
ASICachePolicy policy = _useCacheFirst ? ASIOnlyLoadIfNotCachedCachePolicy
: (ASIAskServerIfModifiedCachePolicy | ASIFallbackToCacheIfLoadFailsCachePolicy);
asiRequest = [ASIHTTPRequest requestWithURL:
[NSURL URLWithString:[requestedUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]; [asiRequest setDownloadCache:[ASIDownloadCache sharedCache]];
[asiRequest setCachePolicy:policy];
[asiRequest setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
// Connection
if (_connectionType == ConnectionTypeAsynchronously) {
[asiRequest setDelegate:self];
[asiRequest startAsynchronous];
// Tell we‘re receiving.
if (!_canceled && [_delegate respondsToSelector:@selector(downloaderDidStart:)])
[_delegate downloaderDidStart:self];
}
else
{
[asiRequest startSynchronous];
NSError *error = [asiRequest error];
if (!error)
{
[self requestFinished:asiRequest];
}
else
{
[self requestFailed:asiRequest];
}
}
[requestedUrl release];
|
3.RestKit
Official website: Http://restkit.org/,Github Open Source project, dealing with the Web services of the Restfull API, this library is very convenient, it also provides a very complete cache mechanism.
Sample:
123456789101112 |
+ (
void
)setCachePolicy:(
BOOL
)useCacheFirst
{
RKObjectManager* objectManager = [RKObjectManager sharedManager];
if (useCacheFirst) {
objectManager.client.cachePolicy = RKRequestCachePolicyEnabled;
//使用本地Cache,如果没有Cache请求服务器
}
else
{
objectManager.client.cachePolicy = RKRequestCachePolicyLoadIfOffline|RKRequestCachePolicyTimeout;
//离线或者超时时使用本地Cache
}
}
|
123456789101112 |
+ (
BOOL
)getHomeTimeline:(NSInteger)maxId
length:(NSInteger)length
delegate:(id<RKObjectLoaderDelegate>)delegate
useCacheFirst:(
BOOL
)useCacheFirst
{
if (delegate == nil)
return NO;
[iKnowAPI setCachePolicy:useCacheFirst];
//...
}
|
The cache request is just RestKit the most basic functionality, and the real power of RestKit is that it's easy to work with the RESTful Web services when interacting (https://github.com/RestKit/RestKit/ Wiki), Restkit can also cache data model into core data:
Core Data Support. Building on top of the object mapping layer, RestKit provides integration with Apple ' s Core Data framework. This support allows RestKit to persist remotely loaded objects directly back into a local store, either as a fast local CA Che or a primary data store is periodically synced with the cloud. RestKit can populate Core data associations for your, allowing natural property based traversal of your Data model. It also provides a nice API on top of the Core Data primitives this simplifies configuration and querying use cases throug H an implementation of the Active Record access pattern.
But in fact Rkrequestcachepolicy has solved most of the cache requirements.
4.SDWebImage
Sdwebimage is the GitHub Open source project: Https://github.com/rs/SDWebImage, which is used for convenient request, cache network images, and is presented to Uiimageview when the request is complete.
Asynchronous image downloader with the cache support with an Uiimageview category.
Sdwebimage is provided as a category in Uiimageview, so it is very simple to use:
123 |
// Here we use the new provided setImageWithURL: method to load the web image [imageView setImageWithURL:[NSURL URLWithString:@ "http://www.domain.com/path/to/image.jpg" ] placeholderImage:[UIImage imageNamed:@ "placeholder.png" ]]; |
Afnetworking also provides a similar function (uiimageview+afnetworking):
12 |
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f)]; [imageView setImageWithURL:[NSURL URLWithString:@ "http://i.imgur.com/r4uwx.jpg" ] placeholderImage:[UIImage imageNamed:@ "placeholder-avatar" ]]; |
Picture in 5.UIWebView Cache
If you use UIWebView to display content, you need to implement 2 points if you want to display it offline:
- Cache HTML page
- Cache images and other elements
Using the network components described above to cache HTML page is convenient, then use WebView loadhtmlstring to load the local HTML page, and the cache picture needs to replace the Nsurlcache public instance for the custom Nsurlcache (UIWebView used is +[nsurlcache Sharedurlcache]):
12345 |
//设置使用自定义Cache机制 LocalSubstitutionCache *cache = [[[LocalSubstitutionCache alloc] init] autorelease]; [cache setMemoryCapacity:4 * 1024 * 1024]; [cache setDiskCapacity:10 * 1024 * 1024]; [NSURLCache setSharedURLCache:cache]; |
Custom Nsurlcache:
12345678910 |
#import <Foundation/Foundation.h> @interface LocalSubstitutionCache : NSURLCache { NSMutableDictionary *cachedResponses; } + (NSString *)pathForURL:(NSURL*)url; @end |
See Newsreader in detail in the LOCALSUBSTITUTIONCACHE.H/.M and webviewcontroller.m in the Viewdidload,news Reader Open source project here is the reference:/HTTP Cocoawithlove.com/2010/09/substituting-local-data-for-remote.html
The Open source project introduced in newsreader, "IOS News reader Open Source project", improves the offline usage experience:
In the absence of the network to use all the data has been cache: articles, pictures, audio and so on, the main program has been introduced in the above, detailed see source: Https://github.com/cubewang/NewsReader.
The newsreader project because of the historical evolution of the cause has been a bit large, need to be further reconstructed, in subsequent projects, our client structure is more streamlined.
How to improve your offline experience with iOS apps