Ben Copsey

Stop using an NSTimer to update progress, we just do it from the main request loop instead

Added default values for didFailSelector and didFinishSelector for the simple cases
Several small bug fixes
Order of methods in implementation now matches the order of those in the header
@@ -10,9 +10,11 @@ @@ -10,9 +10,11 @@
10 #import <Cocoa/Cocoa.h> 10 #import <Cocoa/Cocoa.h>
11 #import "ASIProgressDelegate.h" 11 #import "ASIProgressDelegate.h"
12 12
  13 +
  14 +
13 @interface ASIHTTPRequest : NSOperation { 15 @interface ASIHTTPRequest : NSOperation {
14 16
15 - //The url for this operation, should include get params in the query string where appropriate 17 + //The url for this operation, should include GET params in the query string where appropriate
16 NSURL *url; 18 NSURL *url;
17 19
18 //The delegate, you need to manage setting and talking to your delegate in your subclasses 20 //The delegate, you need to manage setting and talking to your delegate in your subclasses
@@ -78,103 +80,145 @@ @@ -78,103 +80,145 @@
78 //Size of the POST payload 80 //Size of the POST payload
79 double postLength; 81 double postLength;
80 82
81 - //Timer used to update the progress delegates  
82 - NSTimer *progressTimer;  
83 -  
84 //The total amount of downloaded data 83 //The total amount of downloaded data
85 double totalBytesRead; 84 double totalBytesRead;
86 85
  86 + //Last amount of data read (used for incrementing progress)
  87 + double lastBytesRead;
  88 + //Last amount of data sent (used for incrementing progress)
  89 + double lastBytesSent;
  90 +
87 //Realm for authentication when credentials are required 91 //Realm for authentication when credentials are required
88 NSString *authenticationRealm; 92 NSString *authenticationRealm;
89 93
  94 + //This lock will block the request until the delegate supplies authentication info
  95 + NSConditionLock *authenticationLock;
  96 +
90 //Called on the delegate when the request completes successfully 97 //Called on the delegate when the request completes successfully
91 SEL didFinishSelector; 98 SEL didFinishSelector;
92 99
93 //Called on the delegate when the request fails 100 //Called on the delegate when the request fails
94 SEL didFailSelector; 101 SEL didFailSelector;
95 102
96 - //This lock will block the request until the delegate supplies authentication info  
97 - NSConditionLock *authenticationLock;  
98 } 103 }
99 104
  105 +#pragma mark init / dealloc
  106 +
100 // Should be an HTTP or HTTPS url, may include username and password if appropriate 107 // Should be an HTTP or HTTPS url, may include username and password if appropriate
101 - (id)initWithURL:(NSURL *)newURL; 108 - (id)initWithURL:(NSURL *)newURL;
102 109
  110 +#pragma mark delegate configuration
  111 +
  112 +// Delegate will get messages when the request completes, fails or when authentication is required
  113 +- (void)setDelegate:(id)newDelegate;
  114 +
  115 +// upload progress delegate (usually an NSProgressIndicator) is sent information on upload progress
  116 +- (void)setUploadProgressDelegate:(id)newDelegate;
  117 +
  118 +// download progress delegate (usually an NSProgressIndicator) is sent information on download progress
  119 +- (void)setDownloadProgressDelegate:(id)newDelegate;
  120 +
  121 +#pragma mark setup request
  122 +
  123 +//Add a custom header to the request
  124 +- (void)addRequestHeader:(NSString *)header value:(NSString *)value;
  125 +
103 //Add a POST variable to the request 126 //Add a POST variable to the request
104 - (void)setPostValue:(id)value forKey:(NSString *)key; 127 - (void)setPostValue:(id)value forKey:(NSString *)key;
105 128
106 //Add the contents of a local file as a POST variable to the request 129 //Add the contents of a local file as a POST variable to the request
107 - (void)setFile:(NSString *)filePath forKey:(NSString *)key; 130 - (void)setFile:(NSString *)filePath forKey:(NSString *)key;
108 131
109 -//Add a custom header to the request 132 +// When set, username and password will be presented for HTTP authentication
110 -- (void)addRequestHeader:(NSString *)header value:(NSString *)value; 133 +- (void)setUsername:(NSString *)newUsername andPassword:(NSString *)newPassword;
  134 +
  135 +// When true, authentication information will automatically be stored in (and re-used from) the keychain
  136 +- (void)setUsesKeychain:(BOOL)shouldUseKeychain;
111 137
112 //the results of this request will be saved to downloadDestinationPath, if it is set 138 //the results of this request will be saved to downloadDestinationPath, if it is set
113 - (void)setDownloadDestinationPath:(NSString *)newDestinationPath; 139 - (void)setDownloadDestinationPath:(NSString *)newDestinationPath;
114 -- (NSString *)downloadDestinationPath;  
115 140
116 -// When set, username and password will be presented for HTTP authentication 141 +- (NSString *)downloadDestinationPath;
117 -- (void)setUsername:(NSString *)newUsername andPassword:(NSString *)newPassword;  
118 -  
119 -// Delegate will get messages when the request completes, fails or when authentication is required  
120 -- (void)setDelegate:(id)newDelegate;  
121 142
122 -// Called on the delegate when the request completes successfully 143 +// This selector will be called on the delegate when the request completes successfully
123 - (void)setDidFinishSelector:(SEL)selector; 144 - (void)setDidFinishSelector:(SEL)selector;
124 145
125 -// Called on the delegate when the request fails 146 +// This selector will be called on the delegate when the request fails
126 - (void)setDidFailSelector:(SEL)selector; 147 - (void)setDidFailSelector:(SEL)selector;
127 148
128 -// upload progress delegate (usually an NSProgressIndicator) is sent information on upload progress 149 +#pragma mark get information about this request
129 -- (void)setUploadProgressDelegate:(id)newDelegate;  
130 150
131 -// download progress delegate (usually an NSProgressIndicator) is sent information on download progress 151 +// Accessors for getting information about the request (useful for auth dialogs)
132 -- (void)setDownloadProgressDelegate:(id)newDelegate; 152 +- (NSString *)authenticationRealm;
  153 +- (NSString *)host;
133 154
134 -// When true, authentication information will automatically be stored in (and re-used from) the keychain 155 +// Contains a description of the error that occurred if the request failed
135 -- (void)setUsesKeychain:(BOOL)shouldUseKeychain; 156 +- (NSError *)error;
  157 +- (void)setError:(NSError *)newError;
136 158
137 // Will be true when the request is complete (success or failure) 159 // Will be true when the request is complete (success or failure)
138 - (BOOL)complete; 160 - (BOOL)complete;
  161 +- (BOOL)isFinished; //Same thing, for NSOperationQueues to read
  162 +
  163 +// Get total amount of data received so far for this request
  164 +- (double)totalBytesRead;
139 165
140 // Returns the contents of the result as an NSString (not appropriate for binary data!) 166 // Returns the contents of the result as an NSString (not appropriate for binary data!)
141 - (NSString *)dataString; 167 - (NSString *)dataString;
142 168
143 -// Accessors for getting information about the request (useful for auth dialogs) 169 +#pragma mark request logic
144 -- (NSString *)authenticationRealm;  
145 -- (NSString *)host;  
146 170
147 -// Contains a description of the error that occurred if the request failed 171 +// Start loading the request
148 -- (NSError *)error; 172 +- (void)loadRequest;
149 173
  174 +// Cancel loading and clean up
  175 +- (void)cancelLoad;
150 176
151 -// CFnetwork event handlers 177 +#pragma mark upload/download progress
152 -- (void)handleStreamComplete;  
153 -- (void)handleStreamError;  
154 -- (void)handleBytesAvailable;  
155 -- (void)handleNetworkEvent:(CFStreamEventType)type;  
156 178
157 -// Start loading the request 179 +// Called on main thread to update progress delegates
158 -- (void)loadRequest; 180 +- (void)updateProgressIndicators;
  181 +- (void)resetUploadProgress:(NSNumber *)max;
  182 +- (void)updateUploadProgress;
  183 +- (void)resetDownloadProgress:(NSNumber *)max;
  184 +- (void)updateDownloadProgress;
  185 +
  186 +#pragma mark handling request complete / failure
  187 +
  188 +//Called when a request completes successfully - defaults to: @selector(requestFinished:)
  189 +- (void)requestFinished;
  190 +
  191 +//Called when a request fails - defaults to: @selector(requestFailed:)
  192 +- (void)failWithProblem:(NSString *)problem;
  193 +
  194 +#pragma mark http authentication stuff
159 195
160 // Reads the response headers to find the content length, and returns true if the request needs a username and password (or if those supplied were incorrect) 196 // Reads the response headers to find the content length, and returns true if the request needs a username and password (or if those supplied were incorrect)
161 - (BOOL)isAuthorizationFailure; 197 - (BOOL)isAuthorizationFailure;
162 198
163 -// Apply authentication information and resume the request after an authentication challenge  
164 -- (void)applyCredentialsAndResume;  
165 -  
166 // Unlock (unpause) the request thread so it can resume the request 199 // Unlock (unpause) the request thread so it can resume the request
167 // Should be called by delegates when they have populated the authentication information after an authentication challenge 200 // Should be called by delegates when they have populated the authentication information after an authentication challenge
168 - (void)retryWithAuthentication; 201 - (void)retryWithAuthentication;
169 202
170 -// Cancel loading and clean up 203 +// Apply authentication information and resume the request after an authentication challenge
171 -- (void)cancelLoad; 204 +- (void)applyCredentialsAndResume;
172 205
173 -// Called from timer on main thread to update progress delegates 206 +// Look for somewhere we can get authentication information from
174 -- (void)updateUploadProgress; 207 +- (void)applyCredentialsLoad;
175 -- (void)updateDownloadProgress; 208 +
  209 +// Customise or overidde this to have a generic error for authentication failure
  210 +- (NSError *)authenticationError;
176 211
177 -#pragma mark keychain stuff 212 +#pragma mark stream status handlers
  213 +
  214 +// CFnetwork event handlers
  215 +- (void)handleNetworkEvent:(CFStreamEventType)type;
  216 +- (void)handleBytesAvailable;
  217 +- (void)handleStreamComplete;
  218 +- (void)handleStreamError;
  219 +
  220 +
  221 +#pragma mark keychain storage
178 222
179 //Save credentials to the keychain 223 //Save credentials to the keychain
180 + (void)saveCredentials:(NSURLCredential *)credentials forHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm; 224 + (void)saveCredentials:(NSURLCredential *)credentials forHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;
@@ -182,10 +226,16 @@ @@ -182,10 +226,16 @@
182 //Return credentials from the keychain 226 //Return credentials from the keychain
183 + (NSURLCredential *)savedCredentialsForHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm; 227 + (NSURLCredential *)savedCredentialsForHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;
184 228
185 -//Called when a request completes successfully 229 +//Remove credentials from the keychain
186 -- (void)requestFinished; 230 ++ (void)removeCredentialsForHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;
  231 +
  232 +
  233 +
  234 +
  235 +
  236 +
  237 +
  238 +
187 239
188 -//Called when a request fails  
189 -- (void)failWithProblem:(NSString *)problem;  
190 240
191 @end 241 @end
This diff is collapsed. Click to expand it.
@@ -13,4 +13,5 @@ @@ -13,4 +13,5 @@
13 - (void)setDoubleValue:(double)newValue; 13 - (void)setDoubleValue:(double)newValue;
14 - (void)incrementBy:(double)amount; 14 - (void)incrementBy:(double)amount;
15 - (void)setMaxValue:(double)newMax; 15 - (void)setMaxValue:(double)newMax;
  16 +- (double)maxValue;
16 @end 17 @end
@@ -27,6 +27,10 @@ @@ -27,6 +27,10 @@
27 - (IBAction)simpleURLFetch:(id)sender 27 - (IBAction)simpleURLFetch:(id)sender
28 { 28 {
29 ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]] autorelease]; 29 ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]] autorelease];
  30 +
  31 + //Customise our user agent, for no real reason
  32 + [request addRequestHeader:@"User-Agent" value:@"ASIHTTPRequest"];
  33 +
30 [request start]; 34 [request start];
31 if ([request dataString]) { 35 if ([request dataString]) {
32 [htmlSource setString:[request dataString]]; 36 [htmlSource setString:[request dataString]];
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.