I have question, in my application I need to have a connection and a webview to display the web content.
The problem is that I have a username and a password which need to be right in order to get a connection. Now I want to have an alert that comes up if the username is wrong. The
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
does not work for this, because if the username or the password is wrong it will continue loading (even though it won't display anything).
Is there a possibilty to 'tell' webview to set a time interval and then display an alert?
THANK YOU SO MUCH!
If you're authenticating with your server via HTTP authentication (per your comment above) then I would do this differently. When the user enters their username/pwd, make a request to any page (something lightweight) using NSURLConnection. If the username/password are incorrect you can handle the failures in the NSURLConnectionDelegate methods and prompt your user for a new username/password.
You can also do this with the iOS 5 version of NSURLConnection instead of the delegate methods but the docs aren't very good.
When this first request succeeds then load the web view.
EDIT: added example of using NSURLConnection to check if HTTP auth succeeds
Ok, here's a simple example. You can make this better by allowing NSURLConnection to load your intended request and if it succeeds load the response data into the webView vs initiating a new request. Read the URL Loading System docs to learn more about how to use NSURLConnection.
In your webView delegate, initiate an NSURLConnection with a request to the same domain as the webView request with the user credentials as follows:
- (void)performHTTPAuthRequest
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://%#:%##test.starsightings.com", username, password]]];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
}
// if the request succeeds, credentials must be good so load the webView
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// request completed successfully so username/password must be good
[self.webView loadRequest:theRequest];
}
// ignore the failure
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
}
// if we get an auth challenge, the credentials are bad so cancel the request and alert the user
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
[[challenge sender] cancelAuthenticationChallenge:challenge];
// alert user that username/pwd is invalid
}
Related
The code below gives me an NSLog redirect location on a tinyurl link when clicking on a tinyurl link. However, if I remove the following piece of code [[UIApplication sharedApplication] openURL:[request URL]];, it will give me the actual website in NSLog and not the tinyurl link. How can I make it where I can have the actual website URL in NSLog while the share application code is presented?
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#"Redirect Location: %#",[request.URL absoluteString]);
[[UIApplication sharedApplication] openURL:[request URL]];
}
Short answer:
Using UIWebViewDelegate method shouldStartLoadWithRequest is not a great mechanism for figuring out to which site you'll be redirected (especially since, judging from your code, you'll ultimately opening it in an external app, not your UIWebView), because you're getting shouldStartLoadWithRequest before the redirect takes place. You can, though, use NSURLConnection and NSURLConnectionDataDelegate methods to figure out where you'll eventually be redirected.
Long answer:
If you look at shouldStartLoadWithRequest, if you return YES, you'll let the UIWebView follow the redirect requests. Consider the following shouldStartLoadWithRequest:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSLog(#"%#", request.URL);
return YES;
}
If you use this with the a random bit.ly URL, say, http://nyti.ms/Yi6EAk, you'll see the following log:
2013-03-12 21:23:31.418 webtest[6959:c07] http://nyti.ms/Yi6EAk
2013-03-12 21:23:31.511 webtest[6959:c07] http://bit.ly/Yi6EAk?cc=0d7134b272b1004cb954d0400076e9fa
2013-03-12 21:23:31.560 webtest[6959:c07] http://www.nytimes.com/2013/03/13/us/politics/ryans-plan-aims-to-balance-budget-in-10-years.html?hp&_r=0
That third call to shouldStartLoadWithRequest is the actual URL for which I defined the bit.ly redirect URL, i.e. the final destination of two consecutive redirects. But if your shouldStartLoadWithRequest returned NO, then you'll never figure out to which site it would ultimately be redirected. (And by the way, your shouldStartLoadWithRequest should definitely return YES or NO ... your sample doesn't return either.)
As you can see, because shouldStartLoadWithRequest happens before the redirect has a chance to take place, you'll see each and every redirect taking place. Depending upon what the resulting site does, you may see subsequent shouldStartLoadWithRequest calls as the page retrieves extra content. This makes this an awkward mechanism for finding out what site to which you were ultimately redirected.
If you really need the site you're being redirected to, you might want to use NSURLConnection, instead. While that is generally used for actually retrieving the data from the server, it can also be used for capturing the redirects (but not suffering from the problems of the UIWebViewDelegate method shouldStartLoadWithRequest, where it's tough to differentiate between genuine redirects from just random additional content that the page may subsequently request).
So consider the following:
self.url = [NSURL URLWithString:#"http://nyti.ms/Yi6EAk"];
NSURLRequest *request = [NSURLRequest requestWithURL:self.url];
[NSURLConnection connectionWithRequest:request delegate:self];
You can then implement connection:willSendRequest:redirectResponse:, a NSURLConnectionDataDelegate method, that will track the various redirects:
- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response
{
self.url = request.URL;
return request;
}
Clearly, because you're using NSURLConnection to track the redirects, but we don't really care about the responseData that we generally use NSURLConnection to retrieve, we can just cancel the connection as soon as you receive a good response (confident that we already know to which site were finally redirected):
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[connection cancel];
NSLog(#"Ok, we now know that the resulting URL is %#", self.url);
}
You might, by the way, also want to capture connection errors, for example:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Ok, we failed trying to retrieve data from %#", self.url);
}
In closing, it's worth pointing out that this technique, of making the HTTP request with NSURLConnection and letting it follow the whole series of redirects, is a pretty inefficient process, so you'll have to decide whether it's worth it. But this is one way to figure out where your HTTP redirects will lead you.
One final caveat, this captures traditional redirects, but if the page is doing any client-side JavaScript redirects, I don't think this technique will work. It works for the vast majority of redirected HTTP requests, though.
I'm making an app that downloads data from a plist and uses that data in a tableview. Is there a way to check whether a connection to a url is successful and then whether the download was successful? Or maybe a tutorial that implements something like this?
Thanks
you must implement this delegate of NSURLConnection
//send the request
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
in the case of connection failure,this method will be executed
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSlog(#"no connection");
}
How to load a webpage (Https using a self signed certificate) on the UIWebView (iOS)? I tried using NSURLConnection and I am able to load the NSMutableData to the UIwebView. But in this case I am not able to see the images in that page.
[yourWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"yourUrlGoesHere"]]];
And about the certificates part if your URL openable in Safari it will open in a webview.
Update for the comment
Try the below
NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:#"yourUrlGoesHere"]];
NSURLConnection *urlConnection=[NSURLConnection connectionWithRequest:req delegate:self];
[yourWebView loadRequest:req];
and implement the following delegate methods in your class,
#pragma mark - NSURLConnection Delegate Methods
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
Self signed certificates most of the time can not be validated by client, thats why the client can not load the data, because it can not validate from server.
Certificates uses domains to validate itself so it is a bit hard to have on development environment.
There is a tool which creates for local environment certificate, i am not sure how it is internally working my best thought is it adds another CA file on your environment.
You may want to check mkcert it is very easy to use nice workaround.
I want to embed a URL inside an iPhone app, that will take the user to a landing page which later on I can redirect that URL to an iTunes App link once it becomes available, all that without resubmitting the App for approval again. Is this possible?
Thanks
Yes. Use the openURL: method of UIApplication to open your landing page URL. When you want to swap it out, have your favourite server-side language perform a 301 or 302 redirect, depending on whether the redirect is permanent or not.
Having said that, if all you want to do is direct people to rate the app or something similar to that, you don't need to swap it out; the application ID is all you need to construct the URL and iTunes Connect gives you that when you register the app, before you upload the binary.
You can use a short URL or any other URL with a redirection, then in your code intercept the redirection to avoid opening Safari if it's not necessary:
Create a NSURLConnection:
NSURL *shortURL = [NSURL URLWithString:#"http://tinyurl.com/xxyy"];
NSURLConnection *conn = [[NSURLConnection alloc]
initWithRequest:[NSURLRequest requestWithURL:shortURL]
delegate:self
startImmediately:YES];
Define some delegate methods. In your class, define an NSURL property finalDestination to hold the final URL.
- (NSURLRequest *)connection:(NSURLConnection *)connection
willSendRequest:(NSURLRequest *)request
redirectResponse:(NSURLResponse *)response
{
finalDestination = [response URL];
return request;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if (!finalDestination) {
/* redirect failed, use backup url */
finalDestination = /* backup url */
}
[[UIApplication sharedApplication] openURL:finalDestination];
}
Also, check Apple Technical Q&A Launching the App Store from an iPhone application.
(Note: ARC code)
I need a little help here!!!
If string 'url' contains the address to web server, how do i check whether my web server is up or down?
I got some codes to check Internet connectivity. But even if we have internet connectivity how do we know server is up or not? Is there any better way to do that?
Thank You
You could do a request,
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:20.0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest
delegate:self];
Now if you implement (along with all other delegate methods)
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
you will get either succes or error.
Post a request, get the response. If you get a response, the server is up, if not its down..