Permalink
Browse files

Handling parallel requests

Summary: Current SDK doesn't support multiple requests at the same time. To
change this I added a new container to the Facebook class that stores all the
requests. Whenever the request finishes it's work (by loading the response or by
returning an error) we remove it from the container. Since FBRequests are
autorelased they will be deleted at the end of the event loop.

Test Plan: Check if the app works + tried to call the GetMe API method twice.

Reviewers: yariv, toddkrabach, jonathan

Reviewed By: toddkrabach

CC: yariv, toddkrabach, jonathan, jimbru, lshepard, jgabbard, kamil

Differential Revision: 378930
  • Loading branch information...
1 parent e79d072 commit db90ce04f337466ab675464cef8d51cecb49965b Kamil Kraszewski committed with Kamil Kraszewski Dec 15, 2011
Showing with 68 additions and 36 deletions.
  1. +18 −2 src/FBRequest.h
  2. +20 −13 src/FBRequest.m
  3. +3 −3 src/Facebook.h
  4. +27 −18 src/Facebook.m
View
20 src/FBRequest.h
@@ -19,6 +19,14 @@
@protocol FBRequestDelegate;
+enum {
+ kFBRequestStateReady,
+ kFBRequestStateLoading,
+ kFBRequestStateComplete,
+ kFBRequestStateError
+};
+typedef NSUInteger FBRequestState;
+
/**
* Do not use this interface directly, instead, use method in Facebook.h
*/
@@ -29,6 +37,8 @@
NSMutableDictionary* _params;
NSURLConnection* _connection;
NSMutableData* _responseText;
+ FBRequestState _state;
+ NSError* _error;
}
@@ -51,8 +61,14 @@
* standard Objective-C object-to-string conversion facilities.
*/
@property(nonatomic,retain) NSMutableDictionary* params;
-@property(nonatomic,assign) NSURLConnection* connection;
-@property(nonatomic,assign) NSMutableData* responseText;
+@property(nonatomic,retain) NSURLConnection* connection;
+@property(nonatomic,retain) NSMutableData* responseText;
+@property(nonatomic,readonly) FBRequestState state;
+
+/**
+ * Error returned by the server in case of request's failure (or nil otherwise).
+ */
+@property(nonatomic,retain) NSError* error;
+ (NSString*)serializeURL:(NSString *)baseUrl
View
33 src/FBRequest.m
@@ -28,15 +28,20 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
+@interface FBRequest ()
+@property (nonatomic,readwrite) FBRequestState state;
+@end
+
@implementation FBRequest
@synthesize delegate = _delegate,
url = _url,
httpMethod = _httpMethod,
params = _params,
connection = _connection,
- responseText = _responseText;
-
+ responseText = _responseText,
+ state = _state,
+ error = _error;
//////////////////////////////////////////////////////////////////////////////////////////////////
// class public
@@ -247,12 +252,14 @@ - (void)handleResponseData:(NSData *)data {
@selector(request:didLoadRawResponse:)]) {
[_delegate request:self didLoadRawResponse:data];
}
+
+ NSError* error = nil;
+ id result = [self parseJsonResponse:data error:&error];
+ self.error = error;
if ([_delegate respondsToSelector:@selector(request:didLoad:)] ||
[_delegate respondsToSelector:
@selector(request:didFailWithError:)]) {
- NSError* error = nil;
- id result = [self parseJsonResponse:data error:&error];
if (error) {
[self failWithError:error];
@@ -304,7 +311,7 @@ - (void)connect {
}
_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
-
+ self.state = kFBRequestStateLoading;
}
/**
@@ -345,19 +352,19 @@ - (NSCachedURLResponse *)connection:(NSURLConnection *)connection
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[self handleResponseData:_responseText];
- [_responseText release];
- _responseText = nil;
- [_connection release];
- _connection = nil;
+ self.responseText = nil;
+ self.connection = nil;
+
+ self.state = kFBRequestStateComplete;
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[self failWithError:error];
- [_responseText release];
- _responseText = nil;
- [_connection release];
- _connection = nil;
+ self.responseText = nil;
+ self.connection = nil;
+
+ self.state = kFBRequestStateError;
}
@end
View
6 src/Facebook.h
@@ -25,11 +25,11 @@
* and Graph APIs, and start user interface interactions (such as
* pop-ups promoting for credentials, permissions, stream posts, etc.)
*/
-@interface Facebook : NSObject<FBLoginDialogDelegate>{
+@interface Facebook : NSObject<FBLoginDialogDelegate, FBRequestDelegate>{
NSString* _accessToken;
NSDate* _expirationDate;
id<FBSessionDelegate> _sessionDelegate;
- FBRequest* _request;
+ NSMutableSet* _requests;
FBDialog* _loginDialog;
FBDialog* _fbDialog;
NSString* _appId;
@@ -110,4 +110,4 @@
*/
- (void)fbDidLogout;
-@end
+@end
View
45 src/Facebook.m
@@ -30,6 +30,9 @@
static NSString* kSDK = @"ios";
static NSString* kSDKVersion = @"2";
+static NSString *requestFinishedKeyPath = @"finished";
+static void *finishedContext = @"finishedContext";
+
///////////////////////////////////////////////////////////////////////////////////////////////////
@interface Facebook ()
@@ -93,6 +96,7 @@ - (id)initWithAppId:(NSString *)appId
self = [super init];
if (self) {
+ _requests = [[NSMutableSet alloc] init];
self.appId = appId;
self.sessionDelegate = delegate;
self.urlSchemeSuffix = urlSchemeSuffix;
@@ -104,9 +108,12 @@ - (id)initWithAppId:(NSString *)appId
* Override NSObject : free the space
*/
- (void)dealloc {
+ for (FBRequest* _request in _requests) {
+ [_request removeObserver:self forKeyPath:requestFinishedKeyPath];
+ }
[_accessToken release];
[_expirationDate release];
- [_request release];
+ [_requests release];
[_loginDialog release];
[_fbDialog release];
[_appId release];
@@ -140,15 +147,29 @@ - (FBRequest*)openUrl:(NSString *)url
[params setValue:self.accessToken forKey:@"access_token"];
}
- [_request release];
- _request = [[FBRequest getRequestWithParams:params
- httpMethod:httpMethod
- delegate:delegate
- requestURL:url] retain];
+ FBRequest* _request = [FBRequest getRequestWithParams:params
+ httpMethod:httpMethod
+ delegate:delegate
+ requestURL:url];
+ [_requests addObject:_request];
+ [_request addObserver:self forKeyPath:requestFinishedKeyPath options:0 context:finishedContext];
[_request connect];
return _request;
}
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
+ if (context == finishedContext) {
+ FBRequest* _request = (FBRequest*)object;
+ FBRequestState requestState = [_request state];
+ if (requestState == kFBRequestStateComplete || requestState == kFBRequestStateError) {
+ [_request removeObserver:self forKeyPath:requestFinishedKeyPath];
+ [_requests removeObject:_request];
+ }
+ } else {
+ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+ }
+}
+
/**
* A private function for getting the app's base url.
*/
@@ -634,16 +655,4 @@ - (void)fbDialogNotLogin:(BOOL)cancelled {
}
}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//FBRequestDelegate
-
-/**
- * Handle the auth.ExpireSession api call failure
- */
-- (void)request:(FBRequest*)request didFailWithError:(NSError*)error{
- NSLog(@"Failed to expire the session");
-}
-
@end

0 comments on commit db90ce0

Please sign in to comment.