@interface ViewController () <NSURLConnectionDataDelegate>
@property (nonatomic, strong) NSURLConnection *connection; // we'll use presence or existence of this connection to determine if download is done
@property (nonatomic) NSUInteger length; // the numbers of bytes downloaded from the server thus far
@property (nonatomic, strong) NSDate *startTime; // when did the download start
@end
static CGFloat const kMinimumMegabytesPerSecond = 20;
static CGFloat const kMaximumElapsedTime = 2.0;
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self testDownloadSpeed];
}
- (void)testDownloadSpeed
{
NSURL *url = [NSURL URLWithString:@"http://insert.your.site.here/yourfile"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
self.startTime = [NSDate date];
self.length = 0;
self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
double delayInSeconds = kMaximumElapsedTime;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
if (self.connection)
{
[self.connection cancel];
self.connection = nil;
[self useOffline];
}
});
}
- (CGFloat)determineMegabytesPerSecond
{
NSTimeInterval elapsed;
if (self.startTime)
{
elapsed = [[NSDate date] timeIntervalSinceDate:self.startTime];
return self.length / elapsed / 1024;
}
return -1;
}
- (void)useOnline
{
// use your MKMapView; I'm just updating a text field with the status
self.statusLabel.text = [NSString stringWithFormat:@"successful @ %.1f mb/sec", [self determineMegabytesPerSecond]];
}
- (void)useOffline
{
// use your offline maps; I'm just updating a text field with the status
self.statusLabel.text = [NSString stringWithFormat:@"unsuccessful @ %.1f mb/sec", [self determineMegabytesPerSecond]];
}
#pragma mark - NSURLConnectionDataDelegate methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// I actually want my download speed to factor out latency, so I'll reset the
// starting timer when the download commences
self.startTime = [NSDate date];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
if (self.connection)
{
self.connection = nil;
[self useOffline];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
self.connection = nil;
if ([self determineMegabytesPerSecond] >= kMinimumMegabytesPerSecond)
[self useOnline];
else
[self useOffline];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// you don't need to do anything with the downloaded data;
// just keep track of # of bytes
self.length += [data length];
}
@end
The choice of kMinimumMegabytesPerSecond
and kMaximumElapsedTime
is obviously up to you. The first measures bandwidth, and the second also factors in latency. The thing is, to do accurate bandwidth test, you need to do prolonged and repeated downloads. But you also want to (a) to not use of too much of the user's data plan; nor (b) take too long. So, in my test, I was just downloading a file of 100kb and set my criteria to be loose enough to permit for a certain amount of variation in both latency and download speed, but you should play around with the values and use whatever suits you.
No comments:
Post a Comment