Ben Copsey

ASIWebPageRequests now pass on most delegate calls to their parent's delegate

Improve iPad ASIWebPageRequest sample to show the resources being downloaded
... ... @@ -1636,7 +1636,7 @@ static NSOperationQueue *sharedQueue = nil;
{
if ([*target respondsToSelector:selector]) {
NSMethodSignature *signature = nil;
signature = [[*target class] instanceMethodSignatureForSelector:selector];
signature = [*target methodSignatureForSelector:selector];
NSInvocation *invocation = [[NSInvocation invocationWithMethodSignature:signature] retain];
[invocation setSelector:selector];
... ...
... ... @@ -43,7 +43,6 @@ static NSMutableArray *requestsUsingXMLParser = nil;
{
}
- (void)requestFinished
{
complete = NO;
... ... @@ -114,6 +113,9 @@ static NSMutableArray *requestsUsingXMLParser = nil;
[externalResourceRequest setParentRequest:self];
[externalResourceRequest setReplaceURLsWithDataURLs:[self replaceURLsWithDataURLs]];
[externalResourceRequest setShouldResetDownloadProgress:NO];
[externalResourceRequest setDelegate:self];
[externalResourceRequest setUploadProgressDelegate:self];
[externalResourceRequest setDownloadProgressDelegate:self];
if ([self downloadDestinationPath]) {
[externalResourceRequest setDownloadDestinationPath:[self cachePathForRequest:externalResourceRequest]];
}
... ... @@ -179,42 +181,18 @@ static NSMutableArray *requestsUsingXMLParser = nil;
[externalResourceRequest setParentRequest:self];
[externalResourceRequest setReplaceURLsWithDataURLs:[self replaceURLsWithDataURLs]];
[externalResourceRequest setShouldResetDownloadProgress:NO];
[externalResourceRequest setDelegate:self];
[externalResourceRequest setUploadProgressDelegate:self];
[externalResourceRequest setDownloadProgressDelegate:self];
if ([self downloadDestinationPath]) {
[externalResourceRequest setDownloadDestinationPath:[self cachePathForRequest:externalResourceRequest]];
}
[[self externalResourceQueue] addOperation:externalResourceRequest];
[externalResourceRequest setShowAccurateProgress:YES];
[self incrementDownloadSizeBy:1];
}
[[self externalResourceQueue] go];
}
- (void)updateDownloadProgress
{
if ([self parentRequest]) {
[[self parentRequest] updateDownloadProgress];
return;
}
[super updateDownloadProgress];
}
- (void)setContentLength:(unsigned long long)newContentLength
{
if ([self parentRequest]) {
[[self parentRequest] setContentLength:[[self parentRequest] contentLength]+newContentLength-contentLength];
}
[super setContentLength:newContentLength];
}
- (void)setTotalBytesRead:(unsigned long long)bytes
{
totalBytesRead = bytes;
if ([self parentRequest]) {
[[self parentRequest] setTotalBytesRead:[[self parentRequest] totalBytesRead]+totalBytesRead-lastBytesRead];
lastBytesRead = totalBytesRead;
return;
}
}
- (void)externalResourceFetchSucceeded:(ASIHTTPRequest *)externalResourceRequest
{
NSString *originalPath = [[externalResourceRequest userInfo] objectForKey:@"Path"];
... ... @@ -439,6 +417,52 @@ static NSMutableArray *requestsUsingXMLParser = nil;
xmlXPathFreeContext(xpathCtx);
}
- (BOOL)respondsToSelector:(SEL)selector
{
if ([self parentRequest]) {
return [[self parentRequest] respondsToSelector:selector];
}
//Ok, now check for selectors we want to pass on to the delegate
if (selector == @selector(requestStarted:) || selector == @selector(request:didReceiveResponseHeaders:) || selector == @selector(request:willRedirectToURL:) || selector == @selector(requestFinished:) || selector == @selector(requestFailed:) || selector == @selector(request:didReceiveData:) || selector == @selector(authenticationNeededForRequest:) || selector == @selector(proxyAuthenticationNeededForRequest:)) {
return [delegate respondsToSelector:selector];
} else if (selector == @selector(request:didReceiveBytes:) || selector == @selector(request:incrementDownloadSizeBy:)) {
return [downloadProgressDelegate respondsToSelector:selector];
} else if (selector == @selector(request:didSendBytes:) || selector == @selector(request:incrementUploadSizeBy:)) {
return [uploadProgressDelegate respondsToSelector:selector];
}
return [super respondsToSelector:selector];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
if ([self parentRequest]) {
return [[self parentRequest] methodSignatureForSelector:selector];
}
if (selector == @selector(requestStarted:) || selector == @selector(request:didReceiveResponseHeaders:) || selector == @selector(request:willRedirectToURL:) || selector == @selector(requestFinished:) || selector == @selector(requestFailed:) || selector == @selector(request:didReceiveData:) || selector == @selector(authenticationNeededForRequest:) || selector == @selector(proxyAuthenticationNeededForRequest:)) {
return [(id)delegate methodSignatureForSelector:selector];
} else if (selector == @selector(request:didReceiveBytes:) || selector == @selector(request:incrementDownloadSizeBy:)) {
return [(id)downloadProgressDelegate methodSignatureForSelector:selector];
} else if (selector == @selector(request:didSendBytes:) || selector == @selector(request:incrementUploadSizeBy:)) {
return [(id)uploadProgressDelegate methodSignatureForSelector:selector];
}
return nil;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([self parentRequest]) {
return [[self parentRequest] forwardInvocation:anInvocation];
}
SEL selector = [anInvocation selector];
if (selector == @selector(requestStarted:) || selector == @selector(request:didReceiveResponseHeaders:) || selector == @selector(request:willRedirectToURL:) || selector == @selector(requestFinished:) || selector == @selector(requestFailed:) || selector == @selector(request:didReceiveData:) || selector == @selector(authenticationNeededForRequest:) || selector == @selector(proxyAuthenticationNeededForRequest:)) {
[anInvocation invokeWithTarget:delegate];
} else if (selector == @selector(request:didReceiveBytes:) || selector == @selector(request:incrementDownloadSizeBy:)) {
[anInvocation invokeWithTarget:downloadProgressDelegate];
} else if (selector == @selector(request:didSendBytes:) || selector == @selector(request:incrementUploadSizeBy:)) {
[anInvocation invokeWithTarget:uploadProgressDelegate];
}
}
+ (NSArray *)CSSURLsFromString:(NSString *)string
{
NSMutableArray *urls = [NSMutableArray array];
... ... @@ -496,6 +520,7 @@ static NSMutableArray *requestsUsingXMLParser = nil;
}
}
@synthesize externalResourceQueue;
@synthesize resourceList;
@synthesize parentRequest;
... ...
//
// RequestProgressCell.h
// iPhone
//
// Created by Ben Copsey on 03/10/2010.
// Copyright 2010 All-Seeing Interactive. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RequestProgressCell : UITableViewCell {
UIProgressView *progressView;
}
+ (id)cell;
@property (assign, nonatomic) UIProgressView *progressView;
@end
... ...
//
// RequestProgressCell.m
// iPhone
//
// Created by Ben Copsey on 03/10/2010.
// Copyright 2010 All-Seeing Interactive. All rights reserved.
//
#import "RequestProgressCell.h"
@implementation RequestProgressCell
+ (id)cell
{
RequestProgressCell *cell = [[[RequestProgressCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"RequestProgressCell"] autorelease];
[[cell textLabel] setTextAlignment:UITextAlignmentLeft];
[[cell textLabel] setFont:[UIFont systemFontOfSize:12]];
[cell setProgressView:[[[UIProgressView alloc] initWithFrame:CGRectMake(0,0,100,20)] autorelease]];
[cell setAccessoryView:[cell progressView]];
return cell;
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect f = [[self accessoryView] frame];
[[self accessoryView] setFrame:CGRectMake(f.origin.x, f.origin.y+6, f.size.width, f.size.height)];
}
@synthesize progressView;
@end
... ...
... ... @@ -17,8 +17,10 @@
UITextView *responseField;
UISwitch *replaceURLsSwitch;
ASIWebPageRequest *request;
NSMutableArray *requestsInProgress;
}
- (void)fetchURL:(NSURL *)url;
@property (retain, nonatomic) ASIWebPageRequest *request;
@property (retain, nonatomic) NSMutableArray *requestsInProgress;
@end
... ...
... ... @@ -11,12 +11,13 @@
#import "ASIWebPageRequest.h"
#import "ASIDownloadCache.h"
#import "ToggleCell.h"
#import "RequestProgressCell.h"
@implementation WebPageViewController
- (void)fetchWebPage:(id)sender
{
[self fetchURL:[NSURL URLWithString:[urlField text]]];
}
- (void)clearCache:(id)sender
... ... @@ -27,17 +28,23 @@
- (void)fetchURL:(NSURL *)url
{
[urlField resignFirstResponder];
[self setRequestsInProgress:[NSMutableArray array]];
[[self tableView] reloadSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationBottom];
// This allows our ASIDownloadCache to masquerade as as NSURLCache
// It allows the webView to load the content we downloaded when replaceURLsWithDataURLs is NO
[NSURLCache setSharedURLCache:[ASIDownloadCache sharedCache]];
[request setDelegate:nil];
[request cancel];
[self setRequest:[ASIWebPageRequest requestWithURL:url]];
[request setDidFailSelector:@selector(webPageFetchFailed:)];
[request setDidFinishSelector:@selector(webPageFetchSucceeded:)];
[request setDelegate:self];
[request setDownloadProgressDelegate:self];
[request setShowAccurateProgress:NO];
[request setReplaceURLsWithDataURLs:[replaceURLsSwitch isOn]];
... ... @@ -68,6 +75,7 @@
[urlField setText:[[theRequest url] absoluteString]];
}
// We'll take over the page load when the user clicks on a link
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)theRequest navigationType:(UIWebViewNavigationType)navigationType
{
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
... ... @@ -77,6 +85,32 @@
return YES;
}
// At time of writing ASIWebPageRequests do not support automatic progress tracking across all requests needed for a page
// The code below shows one approach you could use for tracking progress - it creates a new row with a progress indicator for each resource request
// However, you could use the same approach and keep track of an overal total to show progress
- (void)requestStarted:(ASIWebPageRequest *)theRequest
{
[[self requestsInProgress] addObject:theRequest];
[[self tableView] beginUpdates];
[[self tableView] insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:[[self requestsInProgress] count]-1 inSection:2]] withRowAnimation:UITableViewRowAnimationBottom];
[[self tableView] endUpdates];
}
- (void)request:(ASIHTTPRequest *)theRequest didReceiveBytes:(long long)newLength
{
NSInteger requestNumber = [[self requestsInProgress] indexOfObject:theRequest];
if (requestNumber != NSNotFound) {
RequestProgressCell *cell = (RequestProgressCell *)[[self tableView] cellForRowAtIndexPath:[NSIndexPath indexPathForRow:requestNumber inSection:2]];
[[cell progressView] setProgress:[theRequest totalBytesRead]/([theRequest contentLength]+[theRequest partialDownloadSize])];
}
}
- (void)request:(ASIHTTPRequest *)theRequest incrementDownloadSizeBy:(long long)newLength
{
[self request:theRequest didReceiveBytes:0];
}
/*
Most of the code below here relates to the table view, and isn't that interesting
*/
... ... @@ -147,6 +181,18 @@ static NSString *intro = @"ASIWebPageRequest lets you download complete webpages
replaceURLsSwitch = [(ToggleCell *)cell toggle];
}
} else if ([indexPath section] == 2) {
cell = [tableView dequeueReusableCellWithIdentifier:@"RequestProgressCell"];
if (!cell) {
cell = [RequestProgressCell cell];
}
ASIHTTPRequest *theRequest = [[self requestsInProgress] objectAtIndex:[indexPath row]];
[[cell textLabel] setText:[[theRequest url] absoluteString]];
if ([theRequest contentLength] > 0) {
[[(RequestProgressCell *)cell progressView] setProgress:[theRequest totalBytesRead]/([theRequest contentLength]+[theRequest partialDownloadSize])];
}
} else if ([indexPath section] == 3) {
cell = [tableView dequeueReusableCellWithIdentifier:@"Response"];
if (!cell) {
... ... @@ -156,7 +202,6 @@ static NSString *intro = @"ASIWebPageRequest lets you download complete webpages
}
[responseField setFrame:CGRectMake(5,5,tableWidth-tablePadding,180)];
}
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell;
... ... @@ -204,6 +249,8 @@ static NSString *intro = @"ASIWebPageRequest lets you download complete webpages
{
if (section == 1) {
return 2;
} else if (section == 2) {
return [requestsInProgress count];
}
return 1;
}
... ... @@ -226,8 +273,10 @@ static NSString *intro = @"ASIWebPageRequest lets you download complete webpages
} else {
return 50;
}
} else {
} else if ([indexPath section] == 3) {
return 200;
} else {
return 34;
}
}
... ... @@ -238,8 +287,9 @@ static NSString *intro = @"ASIWebPageRequest lets you download complete webpages
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
return 4;
}
@synthesize request;
@synthesize requestsInProgress;
@end
... ...
This diff was suppressed by a .gitattributes entry.