Sunday 24 April 2016

iOS / iPhone Network ETag / HTTP 304 support

Your server team now enabled the ETag (server no change response HTTP 304) then how could you identify that this is going fine with your app, now NSURLConnection can do this, but not implicit. You need to do it by your way.
Nothing to worry just one line of code will do it.

NSMutableURLRequest *request = ...
request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;

A very good article about NSURLCache.

Don't forget to increase the cache size by

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024
                                                       diskCapacity:20 * 1024 * 1024
                                                           diskPath:nil];
  [NSURLCache setSharedURLCache:URLCache];
}




Still confuse that data actually coming from cache response or server response, now what to do? I have tested it on the AFNetworking class. Use this code for testing purpose. Cache response block will call when your data coming from server and it request iOS to cache it. If your response is 304 ( ETag - If-None-Match / If-Modified-Since) then this cache response block will not call.

At the file location : AFHTTPRequestOperationManager.m

step 1.  request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;

step 2. 
    BOOL __block responseFromCache = YES;
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSString* source = responseFromCache ? @"CACHE" : @"SERVER";
        NSLog(@"Request from %@", source);
        success(operation, responseObject);
    }
                                     failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                         failure(operation, error);
                                     }];
    operation.completionQueue = self.completionQueue;
    operation.completionGroup = self.completionGroup;

    [operation setCacheResponseBlock:
     ^NSCachedURLResponse *(NSURLConnection *connection, NSCachedURLResponse *cachedResponse) {
         NSLog(@"cach %@", cachedResponse.response);
         responseFromCache = NO;
         return cachedResponse;
     }];

As below code

//-- AFHTTPRequestOperationManager.m
- (AFHTTPRequestOperation *)HTTPRequestOperationWithHTTPMethod:(NSString *)method
                                                     URLString:(NSString *)URLString
                                                    parameters:(id)parameters
                                                       success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
                                                       failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
    NSError *serializationError = nil;
    NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
    if (serializationError) {
        if (failure) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                failure(nil, serializationError);
            });
#pragma clang diagnostic pop
        }

        return nil;
    }
    request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;
    return [self HTTPRequestOperationWithRequest:request success:success failure:failure];
}

- (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)request
                                                    success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
                                                    failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    operation.responseSerializer = self.responseSerializer;
    operation.shouldUseCredentialStorage = self.shouldUseCredentialStorage;
    operation.credential = self.credential;
    operation.securityPolicy = self.securityPolicy;
    
    
    BOOL __block responseFromCache = YES;
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSString* source = responseFromCache ? @"CACHE" : @"SERVER";
        NSLog(@"Request from %@", source);
        success(operation, responseObject);
    }
                                     failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                         failure(operation, error);
                                     }];
    operation.completionQueue = self.completionQueue;
    operation.completionGroup = self.completionGroup;

    [operation setCacheResponseBlock:
     ^NSCachedURLResponse *(NSURLConnection *connection, NSCachedURLResponse *cachedResponse) {
         NSLog(@"cach %@", cachedResponse.response);
         responseFromCache = NO;
         return cachedResponse;
     }];
    
    return operation;
}


No comments:

Post a Comment