Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Facebook class of iPhone Facebook SDK have cancel method?

Is there anyway to cancel a Facebook object's pending request?

I can't find any methods in Facebook.h, or a way to access the underlying NSURLConnection object. If I press back on the navigation bar and the their is a pending asynchronous Facebook request, the request tries to send a message to a deallocated view once the response has come, causing the application to crash.

like image 434
BU_Number20 Avatar asked Jan 20 '11 20:01

BU_Number20


People also ask

How to Add Facebook SDK to iOS app?

In Xcode, click File > Swift Packages > Add Package Dependency. In the dialog that appears, enter the repository URL: https://github.com/facebook/facebook-ios-sdk. In Version, select Up to Next Major and the default option. Complete the prompts to select the libraries you want to use in your project.

Does Facebook SDK use IDFA?

The Facebook SDK includes code to access Apple's Advertising Identifier (IDFA), but that code is only executed in certain situations.

What does Facebook SDK do?

The Facebook SDK is a set of software components that developers can include in their mobile app to understand how people use the app, run optimized marketing campaigns and enable Facebook login and social sharing.


2 Answers

For anyone who comes across this question, it appears that Matt's observation does not apply to the newest facebook-iphone-sdk. The parameters are no longer explicitly retained in the relevant method:

+ (FBRequest *)getRequestWithParams:(NSMutableDictionary *) params
                         httpMethod:(NSString *) httpMethod
                           delegate:(id<FBRequestDelegate>) delegate
                         requestURL:(NSString *) url {

  FBRequest* request = [[[FBRequest alloc] init] autorelease];
  request.delegate = delegate;
  request.url = url;
  request.httpMethod = httpMethod;
  request.params = params;
  request.connection = nil;
  request.responseText = nil;

So memory management for the delegate falls back to the property declaration in the .h file:

@property(nonatomic,assign) id<FBRequestDelegate> delegate;

This means a crash is now possible since the delegate object can be deallocated before the FBRequest is completed.

Update:

A possible workaround is suggested in this question to allow cancellation of pending FBRequests.

Update 2:

To avoid a crash in the case where the delegate gets deallocated before the FBRequest finishes, you need to cancel the active FBRequest's connection as you deallocate the delegate (which is basically what Matt suggests in the linked question). However (I'm not sure if this is new), you can do this directly to the FBRequest since it exposes it's NSURLConnection property. So, if you retain your FBRequest object in a property:

@property (nonatomic, retain) FBRequest *myRequest;

and save the request object when you make your call:

self.myRequest = [facebookObj requestWithGraphPath:@"me" andDelegate:self];

you can clean everything up in your dealloc:

- (void)dealloc
{
 if( myRequest ) {
    [[myRequest connection] cancel];
    [[myRequest release];
  }

  ...

  [super dealloc];
}

Obviously, you should probably also release and nil the FBRequest property in the delegate methods once you have processed the response.

like image 181
Tim Isganitis Avatar answered Oct 02 '22 02:10

Tim Isganitis


EDIT As pointed out in Tim's answer to this question, this information is now obsolete with the newest releases of the Facebook iOS SDK.

There is no way to cancel a pending request. However, this shouldn't be crashing your app.

The Facebook class uses the FBRequest class under the hood to make all of its REST or Graph API requests, and this is the class that ends up with a reference to your view (controller?) as its delegate property. Looking at the header for FBRequest:

@interface FBRequest : NSObject {
  id<FBRequestDelegate> _delegate;
  NSString*             _url;
  NSString*             _httpMethod;
  NSMutableDictionary*  _params;
  NSURLConnection*      _connection;
  NSMutableData*        _responseText;
}

@property(nonatomic,assign) id<FBRequestDelegate> delegate;

The assign attribute in the property declaration makes it seem that it stores a weak-ref to your class, but then in FBRequest.m:

+ (FBRequest *)getRequestWithParams:(NSMutableDictionary *) params
                         httpMethod:(NSString *) httpMethod
                           delegate:(id<FBRequestDelegate>) delegate
                         requestURL:(NSString *) url {
  FBRequest* request    = [[[FBRequest alloc] init] autorelease];
  request.delegate      = [delegate retain]; // <- It's retained! (Comment mine)
  request.url           = [url retain];
  request.httpMethod    = [httpMethod retain];
  request.params        = [params retain];
  request.connection    = nil;
  request.responseText  = nil;

  return request;
}

It clearly retains the delegate. So, in the normal flow of your application, when you think your view controller should be deallocated after being popped off the navigation stack, the FBRequest has ensured that it will still be alive to receive the response by taking ownership of it.

This makes it seem like you might have other memory management issues elsewhere in the app.

like image 28
Matt Wilding Avatar answered Oct 02 '22 03:10

Matt Wilding