AFNetworking lib not loading data in offline mode in iOS - ios

I am developing a content reading app in which some data is displayed in a tale view and respective detail views.
I have already completed the app but there is a small bug.
I am using AFNetworking library for online data load and offline caching.
I have defined caching policy as described by following code:
Reachability *reach = [Reachability reachabilityWithHostname:#"google.com"];
if ([reach isReachable]) {
// Reachable
request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60.0];
}
else{
request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReturnCacheDataDontLoad
timeoutInterval:60.0];
}
But, I am having a small problem that if I load some data online and then turn off the internet connection and close the app, and afterwords if I restart the app again in offline mode, the cached data should load but it is not happening.
I also have tried changing the caching policies as defined in this link.
app deployment target : iOS 6.0
devices : universal
xcode version : 6.1
AFNetworking lib version : 2.0

Replace all of the code you posted and just set the request cache policy to NSURLRequestUseProtocolCachePolicy.
As it stands, you're currently making a synchronous reachability query on every request. Either that or worse—it's returning immediately, but always returning before a real reachability state can be determined.

Related

NSURLSessionDownloadTask switching from http to https

I have an AFHTTPSessionManager created NSURLSessionDownloadTask being used to download a video within an app that sometimes when initialized with an http:80 url will convert it to https:443. This is happening before any connection attempt is being made (I added a custom HTTP protocol class via NSURLSessionConfiguration to the session in order to log when the connection is being made).
By the time the request makes it to the
-(NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response
delegate method of my CustomHTTPProtocolDelegate class, the request has been changed to https.
App Transport Security is disabled (NSAllowsArbitraryLoads=true) and this behavior seems to be associated with a particular http-only server (other http-only server have no issue, and the connection is made as http on port 80).
Any idea of what could be going on? Anything else I could do to debug?
Here is how the download task is being created (including the debug custom protocol class):
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionConfiguration* config = [NSURLSessionConfiguration ephemeralSessionConfiguration];
config.protocolClasses = #[[CustomHTTPProtocol class]];
AFHTTPSessionManager *session = [[AFHTTPSessionManager manager] initWithSessionConfiguration:config];
self.downloadTask = [session downloadTaskWithRequest:request progress:&progress destination:^NSURL *(NSURL *targetPath, NSURLResponse *response){
...
[UPDATE]
This issue is causing us a number of headaches, so to help facilitate troubleshooting, I created a small test project to help narrow in on the problem. My simple project does two things, loads a url into a UIWebView and downloads a file using NSURLSessionDownloadTask. The urls for these actions follow this pattern:
WebView URL: https://console.company.com/home.html
Download URL: http://data.company.com/file.txt
And those hostnames resolve to different IPs (different servers).
If I download the file before navigating the webview, then everything is fine, but if the webview loads its URL first, then the download URL will be switched to HTTPS automatically and the initial request for data will fail. One thought we had was that once iOS opens a TLS tunnel for the HTTPS connection that the webview is creating, that it tries to use that same tunnel for all subsequent *.company.com connections. Or at the very least, it assumes all *.company.com connections must also be TLS.
Figured it out. Both servers were sending a HSTS header for all subdomains. Because the networking layer under NSURLSession observes this header, the calls to the HTTP server were being upgraded to HTTPS prior to leaving the client.

wifi is connected and internet is not available iOS

My question is same as this question, but don't get a proper answer.
If I am connected to wifi, but internet is not available/gone it should be notify. Alslo tested using Apple Reachability demo but still its not working.
Steps to reproduce:
1) connect iPhone using tethering on another device.
2) run the apple rechability demo.
3) turn off the cellular data on another device on wich iPhone is connected.
You can simply call the below code and then call NSURLConnection delegate methods. This way even if wifi is connected and internet not available it can be detected.
NSMutableURLRequest *headerRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.com"] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10.0];
headerRequest.HTTPMethod = #"HEAD";
self.headerConnection = [[NSURLConnection alloc] initWithRequest:headerRequest delegate:self];

NSURLConnection randomly fails until device reboot

I have been struggling with an issue where NSURLConnection calls instantly fail. The device needs to be rebooted entirely or Flight Mode needs to be toggled on/off to resolve the problem. Restarting the app (swipe up) alone does not help.
Some facts:
-All URLs are HTTPS, TLS 1.2 compatible with Forward Secrecy. There are no issues with ATS and iOS 9. The error has been present since iOS 7 and remains on 9.2.
-No third party frameworks are used by the app. I use only native NSURLConnection calls that always work, except for when this odd situation occurs.
-No infrastructure/network issues - other devices on same networks (same WiFi for instance) work in the same app at the same time. Going to/from 3G/Wifi makes no difference.
-I always implement willCacheResponse to return nil.
-The service is hosted on AWS Elastic Beanstalk, so some suggested that it might be a DNS caching issue in case of IP address changes - this seems unlikely to me and should trigger multiple errors at once on different devices, which I have never seen.
-The method called is didFailWithError, instantaneously, as if there were no Internet connection on the device at all - all other apps work, however.
-The website that hosts the API used by the app can be browsed with no problems at all times. The website actually makes the same requests to fetch data.
The error code returned is -1003, kCFURLErrorCannotFindHost. I've been following a thread on Git dealing with the same issue to no avail. https://github.com/AFNetworking/AFNetworking/issues/967
I tried using NSURLRequestReloadIgnoringCacheData for all my requests, but that did not help.
With this information, will anyone care to venture a guess what I might be doing wrong? I added the bounty because I have no idea how to approach this problem - especially because it's so inconsistent. And it is definitely not a legitimate error (that is, that the domain could not be found), as the service is operating fine while this happens on random clients.
I create my request with a static method that looks like this. It's been stripped of some non-public info, but basically it just performs a POST request with JSON data. [Controller getSQLHost] just returns a URL - the base domain.
+(NSURLConnection*)initiatePOSTwithJSONDictionary:(NSDictionary*)dictionary toURL:(NSString*)urllocation withDelegate:delegate {
NSMutableDictionary *connectionDictionary = [[NSMutableDictionary alloc] init];
if (dictionary) {
[connectionDictionary setObject:dictionary forKey:#"input"];
}
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:connectionDictionary options:kNilOptions error:nil];
NSURL *url = [NSURL URLWithString:[[Controller getSQLHost] stringByAppendingString:urllocation]];
NSString *postLength = [NSString stringWithFormat:#"%i", (int)[jsonData length]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:jsonData];
return [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
}
Does you delegate implement connectionShouldUseCredentialStorage ? (or respond with YES)
I think the device's keychain is used when this method returns yes which may explain the persisting failure beyond the life time of the running application and why rebooting or otherwise resetting network connectivity "fixes" it. If an authentication failure has been recognized once, it may linger in the key chain for a little while which would then respond immediately without actually going to the server.
What would cause the authentication to register as a failure in the keychain in the first place may depend on a variety of factors. It could be as simple as a typo in the saved password or more convoluted such as some certificate expiration preventing the SSL layer from establishing a secure link.
You're creating NSURLConnections on the current runloop. How many are active at any one time? Have you considered using an NSOperationQueue so that you don't get bitten by load bugs?
Is your delegate thread-safe? If not, that could explain the sporadic-ness of the bug.
You say you don't see the problem often, but others do. Can you borrow their devices and maybe even them and their usage patterns and thus get to see the problem more often?

AFNetworking lib not loading data from cache in offline mode

I am developing a content reading app in which some data is displayed in a tale view and respective detail views.
Now I have already completed the app but there is a small bug.
I am using AFNetworking library for online data load and offline caching.
I have defined caching policy as described by following code.
Reachability *reach = [Reachability reachabilityWithHostname:#"google.com"];
if ([reach isReachable])
{
// Reachable
request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60.0];
}
else
{
request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReturnCacheDataDontLoad
timeoutInterval:60.0];
}
But I am having a small problem that if I load some data online and then turn off the internet connection and close the app.
And afterwords if I restart the app again in offline mode, the cached data should load but it is not happening.
I also have tried changing the caching policies as defined in the following link:
http://blog.originate.com/blog/2014/02/20/afimagecache-vs-nsurlcache/
app deployment target : iOS 6.0
devices : universal
xcode version : 6.1
AFNetworking lib version : 2.0
Any suggestion is appreciated, thanks in advanced

Check if the current Session has expired in ASIHTTPREQUEST

How can i check if the session that i have created using following code
NSURL *myWebserverURL = [NSURL URLWithString:XMLURLAddress];
ASIHTTPRequest *request=[ASIHTTPRequest requestWithURL:myWebserverURL];
[request setTimeOutSeconds:3600];
has expired? My scenario is that when my session is created and if the wifi is turned on and after a minute or two wifi is activated again, the session is expired. So how can i know that this session has expired?
First of all: ASIHTTPRequest is dead. If you're looking for something similar use AFNetworking, or check iOS7 brand new NSURLSession.
But for ASIHTTPRequest: Did you set the following completion blocks?
- (void)setCompletionBlock:(ASIBasicBlock)aCompletionBlock;
- (void)setFailedBlock:(ASIBasicBlock)aFailedBlock;
Another thing what might help you is adding any Reachability implementation to your project, so you can monitor the current connection type.

Resources