In each new version of iOS the browser gets a new user-agent string. I’ve been searching for a way to get the user-agent string from the API but haven’t been able to find a straight forward way to do it. Here’s my solution:

BSWebViewUserAgent.h

#import <Foundation/Foundation.h>
 
@interface BSWebViewUserAgent : NSObject <UIWebViewDelegate> {
	NSString *userAgent;
	UIWebView *webView;
}
@property (nonatomic, retain) NSString *userAgent;
-(NSString*)userAgentString;
@end

BSWebViewUserAgent.m

#import "BSWebViewUserAgent.h"
 
 
@implementation BSWebViewUserAgent
@synthesize userAgent;
 
-(NSString*)userAgentString
{
	webView = [[UIWebView alloc] init];
	webView.delegate = self;
	[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"www.google.com"]]];
 
	// Wait for the web view to load our bogus request and give us the secret user agent.
	while (self.userAgent == nil) 
	{
		// This executes another run loop. 
		[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
	}
 
	return self.userAgent;
}
 
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
	self.userAgent = [request valueForHTTPHeaderField:@"User-Agent"];
 
	// Return no, we don't care about executing an actual request.
	return NO;
}
 
- (void)dealloc 
{
	[webView release];
	[userAgent release];
	[super dealloc];
}
@end

I use a UIWebView, listen to its delegates and load a bogus URL. When shouldStartLoadWithRequest is called the supplied request contains the user-agent string in the header. Because UIWebView  loadRequest is asynchronous and we’re not really loading a request because we return NO in shouldStartLoadWithRequest there’s a loop waiting for the user-agent to be set. To wait for an asynchronous task to complete NSRunLoop is used. Each call to NSRunLoop runMode makes the application execute another loop, in this case executing the loadRequest call for our UIWebView.

Using the class is simple:

BSWebViewUserAgent *agent = [[BSWebViewUserAgent alloc] init];
NSLog(@"User-agent: %@", [agent userAgentString]);
[agent release];

This executes very fast, but if you have found an easier/faster way of extracting the user-agent, please let me know.

Related posts