Permalink
Browse files

Add a synchronous request implementation to TTURLRequest.

Synchronous requests allow you to make network requests from
multi-threaded apps without dealing with locks. You can now make synchronous
requests by calling sendSynchronously on a TTURLRequest object.

Testing: Make a synchronous request using TTURLRequest. All of your standard
delegate methods should still be called.
This change should not affect synchronous requests.

Example code:
TTURLRequest* request = [TTURLRequest requestWithURL:URL delegate:self];
[request sendSynchronously];
  • Loading branch information...
jverkoey committed Nov 26, 2009
1 parent 4358c22 commit 1404c7b5a424da668f768e54437af14b83618ebc
Showing with 89 additions and 0 deletions.
  1. +4 −0 src/TTURLRequest.m
  2. +68 −0 src/TTURLRequestQueue.m
  3. +10 −0 src/Three20/TTURLRequest.h
  4. +7 −0 src/Three20/TTURLRequestQueue.h
View
@@ -257,6 +257,10 @@ - (BOOL)send {
return [[TTURLRequestQueue mainQueue] sendRequest:self];
}
+- (BOOL)sendSynchronously {
+ return [[TTURLRequestQueue mainQueue] sendSynchronousRequest:self];
+}
+
- (void)cancel {
[[TTURLRequestQueue mainQueue] cancelRequest:self];
}
View
@@ -44,6 +44,7 @@ - (void)addRequest:(TTURLRequest*)request;
- (void)removeRequest:(TTURLRequest*)request;
- (void)load:(NSURL*)URL;
+- (void)loadSynchronously:(NSURL*)URL;
- (BOOL)cancel:(TTURLRequest*)request;
@end
@@ -237,6 +238,37 @@ - (void)load:(NSURL*)URL {
}
}
+- (void)loadSynchronously:(NSURL*)URL {
+ // This method simulates an asynchronous network connection. If your delegate isn't being called
+ // correctly, this would be the place to start tracing for errors.
+ TTNetworkRequestStarted();
+
+ TTURLRequest* request = _requests.count == 1 ? [_requests objectAtIndex:0] : nil;
+ NSURLRequest* URLRequest = [_queue createNSURLRequest:request URL:URL];
+
+ NSHTTPURLResponse* response = nil;
+ NSError* error = nil;
+ NSData* data = [NSURLConnection
+ sendSynchronousRequest: URLRequest
+ returningResponse: &response
+ error: &error];
+
+ if (nil != error) {
+ TTNetworkRequestStopped();
+
+ TT_RELEASE_SAFELY(_responseData);
+ TT_RELEASE_SAFELY(_connection);
+
+ [_queue performSelector:@selector(loader:didFailLoadWithError:) withObject:self
+ withObject:error];
+ } else {
+ [self connection:nil didReceiveResponse:(NSHTTPURLResponse*)response];
+ [self connection:nil didReceiveData:data];
+
+ [self connectionDidFinishLoading:nil];
+ }
+}
+
- (BOOL)cancel:(TTURLRequest*)request {
NSUInteger index = [_requests indexOfObject:request];
if (index != NSNotFound) {
@@ -558,6 +590,42 @@ - (BOOL)sendRequest:(TTURLRequest*)request {
return NO;
}
+- (BOOL)sendSynchronousRequest:(TTURLRequest*)request {
+ if ([self loadRequestFromCache:request]) {
+ return YES;
+ }
+
+ for (id<TTURLRequestDelegate> delegate in request.delegates) {
+ if ([delegate respondsToSelector:@selector(requestDidStartLoad:)]) {
+ [delegate requestDidStartLoad:request];
+ }
+ }
+
+ if (!request.URL.length) {
+ NSError* error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorBadURL userInfo:nil];
+ for (id<TTURLRequestDelegate> delegate in request.delegates) {
+ if ([delegate respondsToSelector:@selector(request:didFailLoadWithError:)]) {
+ [delegate request:request didFailLoadWithError:error];
+ }
+ }
+ return NO;
+ }
+
+ request.isLoading = YES;
+
+ // Finally, create a new loader and hit the network (unless we are suspended)
+ TTRequestLoader* loader = [[TTRequestLoader alloc] initForRequest:request queue:self];
+ [_loaders setObject:loader forKey:request.cacheKey];
+
+ // Should be decremented eventually by loadSynchronously
+ ++_totalLoading;
+
+ [loader loadSynchronously:[NSURL URLWithString:request.URL]];
+ TT_RELEASE_SAFELY(loader);
+
+ return NO;
+}
+
- (void)cancelRequest:(TTURLRequest*)request {
if (request) {
TTRequestLoader* loader = [_loaders objectForKey:request.cacheKey];
View
@@ -119,6 +119,16 @@
*/
- (BOOL)send;
+/**
+ * Attempts to send a Synchronous request.
+ *
+ * The request will happen Synchronously, regardless of whether the data is being grabbed from
+ * the network or from the cache.
+ *
+ * @return YES if the request was loaded from the cache.
+ */
+- (BOOL)sendSynchronously;
+
/**
* Cancels the request.
*
@@ -58,6 +58,13 @@
*/
- (BOOL)sendRequest:(TTURLRequest*)request;
+/**
+ * Synchronously loads a request from the cache or the network if it is not in the cache.
+ *
+ * @return YES if the request was loaded from the cache.
+ */
+- (BOOL)sendSynchronousRequest:(TTURLRequest*)request;
+
/**
* Cancels a request that is in progress.
*/

0 comments on commit 1404c7b

Please sign in to comment.