37

How can I change the user-agent of UIWebView in iOS 5?

What I have done so far: Using the delegate call back, intercept the NSURLRequest, create a new url request and set it's user-agent as whatever I want, then download the data and reload the UIWebView with "loadData:MIMEType:....".

Problem: This causes infinite recursion, where I load the data, which calls the delegate back, which intern calls the delegate....

Here's the delegate method:

- (BOOL)webView:(UIWebView *)aWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {



    dispatch_async(kBgQueue, ^{
        NSURLResponse *response = nil;
        NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:[request URL]];
        NSDictionary *headers = [NSDictionary dictionaryWithObject:
                                 @"custom_test_agent" forKey:@"User-Agent"];
        [newRequest setAllHTTPHeaderFields:headers];
        [self setCurrentReqest:newRequest];
        NSData *data = [NSURLConnection sendSynchronousRequest:newRequest 
                                             returningResponse:&response 
                                                         error:nil];
        dispatch_sync(dispatch_get_main_queue(), ^{
            [webView loadData:data 
                     MIMEType:[response MIMEType] 
             textEncodingName:[response textEncodingName] 
                      baseURL:[request URL]];
        });
    });

    return YES;
}
0xSina
  • 20,973
  • 34
  • 136
  • 253

3 Answers3

89

Change the "UserAgent" default value by running this code once when your app starts:

NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"Your user agent", @"UserAgent", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];  

EDIT: I have used this with great success, but want to add additional details. To get a user agent, you can enable the "Developer" menu, set the user agent, and then connect to this site to get it printed out for you: WhatsMyAgent. Likewise you can connect using any kind of mobile device, and get it that way too. BTW this is still working just fine in iOS7+

David H
  • 40,852
  • 12
  • 92
  • 138
Martin Wickman
  • 19,662
  • 12
  • 82
  • 106
  • That works correctly. The issue with the original post about setting it in shouldStartLoadWebRequest: is that method is only called on the top level request, so all the internal requests get the old user-agent. I verified this using a fiddler2 proxy. Setting it in standardUserDefaults causes all requests to get the new user-agent. Thanks for the above code! – peterept Mar 05 '12 at 23:55
  • Finally ... something that Actually works.... THANK A LOT MARTIN.... i even found components on github that surprisingly were too complicated to work with... your solution was simple and easy to implement... – Izac Mac May 29 '12 at 09:11
  • Works on iOS 4.3.3 as well. Anyone who can test it on 4.0? – Filip Radelic Aug 10 '12 at 15:02
  • 2
    Works great! I had to set it in the +(void) initialize{} method in my AppDelegate.mm of my phonegap app – Aki Sep 10 '12 at 22:03
  • super! but is it possible to get current headers and modify it ? – Sergey Kopanev Oct 24 '12 at 18:20
  • 3
    This worked perfectly: + (void)initialize { NSDictionary *dictionary = @{ @"UserAgent" : @"Safari iOS 5.1 - iPhone"}; [[NSUserDefaults standardUserDefaults] registerDefaults:dictionary]; } – David H May 14 '13 at 22:11
  • Will it append this new user agent string to the default user agent string? or will overwrite that? – Adil Malik Sep 26 '13 at 07:26
  • @DavidH, your version fixes part of my problem. Thanks for including the user-agent string! Where did you get it? I'm wondering if a different string would solve the rest of my problem. – JohnK Oct 03 '13 at 19:28
  • @Adil look here for more info. What I used worked for me a while ago, some post on StackOverflow: http://enterpriseios.com/wiki/UserAgent – David H Oct 03 '13 at 21:47
1

In Swift use this to set UserAgent,

func setUserAgent(){

    var userAgent = NSDictionary(objectsAndKeys:  "YourUserAgentName","UserAgent")

    NSUserDefaults.standardUserDefaults().registerDefaults(userAgent as [NSObject : AnyObject])

}

Use this to test,

println(WebView.stringByEvaluatingJavaScriptFromString("navigator.userAgent"));
Mohammad Zaid Pathan
  • 16,304
  • 7
  • 99
  • 130
0

When you send message [aWebView loadData:MIMEType:textEncodingName:baseURL:]

then aWebView shouldStartLoadWithRequest: will be called again, and then again - that is why you get an infinite recursion

You should restrict calling of your dispatch_async() block, for example by using some conventional URL:

- (BOOL)webView:(UIWebView *)aWebView shouldStartLoadWithRequest:(NSURLRequest *)request 
        navigationType:(UIWebViewNavigationType)navigationType {


    if ([[[request URL] absoluteString] isEqualToString:@"http://yourdomain.com/?local=true"]) {
        return YES;
    }


    ...

    dispatch_async(...
            [aWebView loadData:data 
                      MIMEType:[response MIMEType] 
              textEncodingName:[response textEncodingName] 
                       baseURL:[NSURL URLWithString:@"http://yourdomain.com/?local=true"]];

    );
    return NO;
}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
funberry
  • 1
  • 1