简体   繁体   中英

xcode, nslog weird hitch

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, ie 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM