Retrieving UIWebView cache? - ios

I'm trying to make sure that I always have an up to date cached copy of a UIWebView using the following code:
// Set URL to help file on server
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#", HELP_FILE_URL]];
// Check network reachability
wifiReach = [Reachability reachabilityWithHostName:[NSString stringWithFormat:#"%#", SERVER_URL]];
netStatus = [wifiReach currentReachabilityStatus];
// Start activity indicators
[self startAnimation];
// Verify current help file cache if we have network connection...
if (netStatus == ReachableViaWWAN || netStatus == ReachableViaWiFi) {
helpFileRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadRevalidatingCacheData timeoutInterval:30];
} else {
// Network NOT reachable - show (local) cache if it exists
helpFileRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReturnCacheDataDontLoad timeoutInterval:30];
}
// Show help file in a web view
[webView loadRequest:helpFileRequest];
It works fine in most cases except for when I go to Airplane mode without terminating the app. Once in Airplane mode the cached webView shows up fine BUT the UIWebView delegate
(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
is also triggered which I don't want. I only want that to be triggered if the cache is empty! How can I achieve that? (If I terminate the app it works fine.) It's a small detail but I really would like it to work correctly :)

OK - I solved it by identifying the error code in the UIWebView delegate method - see below. I found that the error code is -1008 when the cache is empty ("resource unavailable") and -1009 with data in the cache ("The Internet connection appears to be offline."). Both cases offline, in Airplane mode.
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
NSLog(#"%# : %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
[self stopAnimation];
// No help to display - cache is empty and no Internet connection...
if ([error code] == -1008) {
NSString *alertMessage = #"To make Help available offline, you need to view it at least once when connected to the Internet.";
UIAlertView *alertView =
[[UIAlertView alloc] initWithTitle:#"Help Unavailable"
message:alertMessage
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
NSLog( #"Error code:%d, %#", [error code], [error localizedDescription]);
}

Related

How can manage openfire connection on 2G network?

I created messaging application like whatsApp and hike. Its working on 3G,4G and Wifi network. when user switch to 2G network my app connection is interrupted but whatsApp and hike working perfectly. I posting code where i manage app connection ::
#pragma mark - connect to the server
- (BOOL)connect {
if (!self.xmppStream) {
[self setupStream];
}
NSString *jabberID = [[NSUserDefaults standardUserDefaults] stringForKey:kUserName];
if (![self.xmppStream isDisconnected]) {
return YES;
}
if (jabberID == nil || kXMPPPassword == nil) {
return NO;
}
[self.xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];
[self.xmppStream setHostName:kXMPPHost];
NSError *error = nil;
if (![self.xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error])
{
// UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error" message:[NSString stringWithFormat:#"Can't connect to server %#", [error localizedDescription]] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
// [alertView show];
NSLog(#"errorerrorerrorerrorerrorerror :- %#", error);
return NO;
}
return YES;}
- (void)connectThenSignIn {
if ([_xmppStream isConnecting]) { // Connection error, connection is being established
return ;
}
if ([_xmppStream isDisconnected]) { // If disconnected, a server connection is established
[self connect];
_goToRegisterAfterConnected = NO;
} else if ([_xmppStream isConnected]) {
[self doSignIn];
} }
Please suggest me best way to manage openfire connection on every network (2G, 3G, 4G and wifi).
Those applications are probably using push notifications to receive updates while on unreliable IP networks (like 2G). This allows them to appear online without maintaining a constant connection to a server.
This is difficult to accomplish with XMPP -- the protocol was written with the assumption that users only need to be reachable while they are connected to the server. Some XEP extensions have added partial workarounds, but the protocol as a whole is poorly suited to mobile clients. (This has been a well-known limitation since at least 2014.) You may want to consider alternatives.

Swift: Webview prompt dialog box to reload the current page when network is not available

I am new to iOS App development. I have a sample App which is written in Swift.
I am using a WKWebView in my web application.
However, when the mobile network/Wifi is not available. It is showing blank screen.
I would like to prompt a dialog box to refresh the current page to the user when
1. If network is not present
2. My server is not available to be accessed.
Use WebView delegate method to find network error.
-(void)webView:(UIWebView )webView didFailLoadWithError:(NSError )error
{
NSString *str = [NSString stringWithFormat:#"%li",(long)error.code];
if ([str isEqualToString: #"-1009"])//network unavailable error code
{
UIAlertView *alertView=[[UIAlertView alloc] initWithTitle:#"Network Error" message:#"Internet or Wifi is not available. Please check your network connection & try again." delegate:self cancelButtonTitle:#"Retry" otherButtonTitles:nil];
[alertView show];
str = #"";
}
NSLog(#"%#",[super appUrl]);
}
Then retry in AlertView delegate method
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if(buttonIndex==0){
if ([super appUrl]) {
NSURLRequest* appReq = [NSURLRequest requestWithURL:yourURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
[self.webView loadRequest:appReq];
} }
}
P.S. use similar to work with swift.

How can I detect UIWebview loads an url that needs authentication or not in iOS

I'm making an iOS application that allows 2 users interact with each other. When first user navigates to a URL on his app using UIWebView, I will send this url to the second user. The second user receive this link and use UIWebView to load it.
Everything works well until one person goes into a private zone. For example, when the first user goes to www.google.com and logs into his gmail account. Now I capture this link and send to the second user, who tries to load it, but this fails, because it's a private zone of the first user.
How can the UIWebView of second user know that the received url is in private zone or must authenticate to access it?
Here some illustration codes:
On the first user, when navigates an url like www.google.com. I call this function
- (void)loadRequestUrl:(NSString *)url {
NSLog(#"load request");
//Load request
self.websiteUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:websiteUrl]];
[wbWebview loadRequest:request];
//Send url to partner
//I'm using GCDAsyncSocket to send this url string to our server
//And server will send it to my current partner
//Just example code for sending
[asyncSocket send:url];
}
//On second user. I received url string from a delegate of GCDAsyncSocket. In this delegate I call this function
- (void)receiveUrl:(NSString *)url {
//Just Load request
self.websiteUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:websiteUrl]];
[wbWebview loadRequest:request];
}
Here an example of url that on first user after he logins his google account
https://accounts.google.com.vn/accounts/SetSID?ssdc=1&sidt=ALWU2cscH%252BVqOOjXXIRKgtz4Q8qmIcJ5lE0dy7xh7MISa%252Bw75BNSeOrF3cO91IED8Cy6PfREuDjuXLzdOMEPaaP0p6XZpCzJFQi4w2xAZa9VKubLQ5xk5%252FF%252FOj8KR0f6e5PSav%252Fww0mKEAuPoI0Dtnve600Pj6PERFtvlH3kbt2Y0hk4KEBpn6nk7zAXUdt2wc%252FaHK0%252FufzyfIMI2hkLpCFu1W1XaOIS3zwuGttA5tXjyLb3AeBLmPgfBbsd7hwZWp7IRVJGglde8gAJ%252F%252BmIhQD4eMQa1s7LD8tnuoagx%252BmRzQ4EGqtcAlE%252FGE3e8b1itkh2HXZQZYB612X1NpcPgta1XbgO7IHd0g7HsDEnsqodhHtr9F7vGl4fO%252BCcHFYaHjH3dT2mCjnOwBn%252Bbh0%252FykYpxqbx2W8K%252BHcZp3B4KI166qCPCZvgnvq7QACPsPuWGVrll4Nw2yLK%252FE2bdmFVILfgIpVbY9SheA%253D%253D&continue=http%253A%252F%252Fwww.google.com.vn%252F%253Fgfe_rd%253Dcr%2526ei%253Dgf7EU-TLL-zV8ge_rYCIAw
The second user receives it, but cannot open. I can NOT capture error on any delegate
IMPORTANCE: I don't need to force second user open it, I just want to capture the event to tell the second user that first user went into private zone
To receive and handle authentication challenge in uiwebview , here is the code.
- (void)viewDidLoad
{
// Load the web view with your url
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"yoururl"]]];
isauth = NO;
}
Now for the delegates. This one is called before a new request is loaded into the webview.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
{
if (!isauth) {
isauth = NO;
[[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
return NO;
}
return YES;
}
//in nsurlconnections delegate. This one deals with the authentication challenge. this time set isauth to YES
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
{
if ([challenge previousFailureCount] == 0) {
isauth = YES;
[[challenge sender] useCredential:[NSURLCredential credentialWithUser:#"username" password:#"password" persistence:NSURLCredentialPersistencePermanent] forAuthenticationChallenge:challenge];
}
else
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
// if the authentication is successfully handled than you will get data in this method in which you can reload web view with same request again.
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
{
NSLog(#"received response via nsurlconnection");
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:#"yoururl"]];
[webView loadRequest:urlRequest];
}
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection;
{
return NO;
}
Hope it helps.
thank you.
to get user name and password , there are multiple ways of doing it , you can create your own mechanism for the same .One simple way is.
-
(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge{
NSLog(#"Need Authentication");
UIAlertView *webLogin = [[UIAlertView alloc] initWithTitle:#"Auth"
message:#"Enter User and Password"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK"
, nil];
self. challenge = challenge;
webLogin.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
[webLogin show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
user = [[alertView textFieldAtIndex:0]text];
pass = [[alertView textFieldAtIndex:1]text];
if (buttonIndex == [alertView cancelButtonIndex]) {
[self dismissModalViewControllerAnimated:YES];
}
else if (buttonIndex != [alertView cancelButtonIndex]) {
[self handleChallenge:self.challenge withUser:user password:pass];
}
}
- (void)handleChallenge:(NSURLAuthenticationChallenge *)aChallenge withUser:(NSString *)userName password:(NSString *)password {
NSURLCredential *credential = [[NSURLCredential alloc]
initWithUser:userName password:password
persistence:NSURLCredentialPersistenceForSession];
[[aChallenge sender] useCredential:credential forAuthenticationChallenge:aChallenge];
}

invitePeer timeout in Multipeer Connectivity iOS 7

I am using this method to ask a nearby device to join the session:
When I do it I also start spinning an indicator
[browser invitePeer:key
toSession:session
withContext:nil
timeout:30];
Is there a method called in the moment of timeout? what if the other device goes out of range?
EDIT:
I notice that this state is never called:
if (state == MCSessionStateConnecting) {
NSLog(#"CONNECTING %#", peerID);
}
in case of timeouts on the browser side, you need to watch for the MCSessionStateNotConnected state. i do something like this:
- (void)session:(MCSession *)session
peer:(MCPeerID *)peerID
didChangeState:(MCSessionState)state
{
if (state == MCSessionStateNotConnected)
{
if (self.isWaitingForInvitation)
{
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:NSLocalizedString(#"ERROR_TITLE", nil)
message:NSLocalizedString(#"ERROR_TEXT", nil)
delegate:self
cancelButtonTitle:NSLocalizedString(#"NO", #"Não")
otherButtonTitles:NSLocalizedString(#"YES", #"Sim"),
nil];
dispatch_sync(dispatch_get_main_queue(), ^{
[alertView show];
});
self.isWaitingForInvitation = NO;
}
}
use the dispatch_sync to make the alert popup right away.
Using a timer with a timer interval matching timeout parameter could be better idea.

Open SharePoint URL in UIWebView iPhone iOS XCode - Embedding credential into URL request to avoid prompt for credential

**I am new to iOS development. I am developing small application which can open specified SharePoint site URL without manually passing require credential. The URL I am trying to open needs credential but I want to embed these credential to the request I will make to open the URL ins UIWebView control. I don't want to open the URL in Safari.
Would you please help me finding the solution?**
You can use -connection:didReceiveAuthenticationChallenge: delegate for your problem. First make a normal NSURLConnection as follow,
- (void) someMethod
{
NSURLRequest* request = [[NSURLRequest alloc]
initWithURL:[NSURL urlWithString:#"Your sharepoint web url"]
NSURLConnection* connection = [[NSURLConnection alloc]
initWithRequest:request delegate:self];
[connection release];
[request release];
}
After that your receive the call back. In here you should handle the challenge of credentials.
- (void) connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
// Make sure to use the appropriate authentication method for the server to
// which you are connecting.
if ([[challenge protectionSpace] authenticationMethod] ==
NSURLAuthenticationMethodBasicAuth)
{
// This is very, very important to check. Depending on how your
// security policies are setup, you could lock your user out of his
// or her account by trying to use the wrong credentials too many
// times in a row.
if ([challenge previousFailureCount] > 0)
{
[[challenge sender] cancelAuthenticationChallenge:challenge];
UIAlertView* alert = [[UIAlertView alloc]
initWithTitle:#"Invalid Credentials"
message:#"The credentials are invalid."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
else
{
[challenge useCredential:[NSURLCredential
credentialWithUser:#"someUser"
password:#"somePassword"
persistence:NSURLCredentialPersistenceForSession
forAuthenticationChallenge:challenge]];
}
}
else
{
// Do whatever you want here, for educational purposes,
// I'm just going to cancel the challenge
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
Update
Use this code for this link.
-(void)viewDidLoad{
NSString *strWebsiteUlr = [NSString stringWithFormat:#"http://www.roseindia.net"];
NSURL *url = [NSURL URLWithString:strWebsiteUlr];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestObj];
[webview setDelegate:self]
}
In header file
#interface yourViewController : UIViewController<UIWebViewDelegate>{
Bool _authed;
}
#property (strong, nonatomic) IBOutlet UIWebView *webView;

Resources