Facebook API - How to cancel Graph Request

后端 未结 9 1036
既然无缘
既然无缘 2020-12-16 04:06

I occasionally need to cancel a FaceBook graph request, but there seems to be no cancel or similar method in their API to do so. At the moment, crashes sometimes occur as th

相关标签:
9条回答
  • 2020-12-16 04:45

    For those of us who build the static library and are unable to access the implementation files, a category would be the best way to go.

    For those of us who did not build the static library, using a category would be optimal as well because you don't need to modify the existing files.

    Here is said category.

    // Facebook+Cancel.h
    #import "Facebook.h"
    
    @interface Facebook (Facebook_cancel)
    
    - (void)cancelPendingRequest:(FBRequest *)releasingRequest;
    
    - (void)cancelAllRequests;
    
    @end
    

    And then the .m file

    // Facebook+Cancel.m
    #import "Facebook+Facebook_cancel.h"
    
    @implementation Facebook (Facebook_cancel)
    
    - (void)cancelPendingRequest:(FBRequest *)releasingRequest{
        [releasingRequest.connection cancel];
        if ([_requests containsObject:releasingRequest]) {
            [_requests removeObject:releasingRequest];
            [releasingRequest removeObserver:self forKeyPath:@"state"];
    
        }
    }
    
    - (void)cancelAllRequests {
        for (FBRequest *req in [_requests mutableCopy]) {
            [_requests removeObject:req];
            [req.connection cancel];
            [req removeObserver:self forKeyPath:@"state"];
        }
    }
    
    @end
    

    For those using any other answer, you are causing a memory leak. The Facebook SDK will warn you through NSLog that you have not removed an observer. The fourth line in the cancelAllRequests method fixes this problem.

    0 讨论(0)
  • 2020-12-16 04:49

    I was having a crash with the previous iOS Facebook SDK which was valid in August 2012 whenever I navigated to another view. My solution is based on @staticfiction response:

    Added BOOL viewWillDisappear flag in .h. In -(void) viewWillDisappear: set the flag to YES. Reset flag to NO in -(void) viewDidAppear:

    //in .h define an FBRequest property
    @property (nonatomic, retain) FBRequest * pendingFBRequest;
    
    
     /*
     * Graph API: Search query to get nearby location.
     */
    - (void)apiGraphSearchPlace:(CLLocation *)location {
    
        currentAPICall = kAPIGraphSearchPlace;
        NSString *centerLocation = [[NSString alloc] initWithFormat:@"%f,%f",
                                    location.coordinate.latitude,
                                    location.coordinate.longitude];
        JMYAppDelegate *delegate = (JMYAppDelegate *)[[UIApplication sharedApplication] delegate];
        NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                       @"place",  @"type",
                                       centerLocation, @"center",
                                       @"1000",  @"distance",
                                       nil];
        [centerLocation release];
        pendingFBRequest = [[delegate facebook] requestWithGraphPath:@"search" andParams:params andDelegate:self];
    
        if (viewWillDisappear) {
            [pendingFBRequest.connection cancel];
            [pendingFBRequest setDelegate:nil];
            [self hideActivityIndicator];
        }
    }
    
    0 讨论(0)
  • 2020-12-16 04:51

    In FBRequest.h, I've had to add _delegate = nil; because in my case, the request delegate no longer existed (it was dismissed) which caused a crash.

    0 讨论(0)
  • 2020-12-16 04:51

    Make a CURL call to this URL

    https://graph.facebook.com/REQUEST_ID?method=delete
    
    0 讨论(0)
  • 2020-12-16 04:52

    I'm assuming you're talking about the facebook-ios-sdk project, and the lack of a cancel method in Facebook.h. I noticed this as well, and eventually decided to add my own cancel method. Just to note, the delegate you assign to the request shouldn't ever be dealloc'd and then referenced, because the request retains the delegate. See this similar question. Now, if you find yourself really needing a cancel method for some other reason...

    Adding a cancel method:
    Facebook requests are made in an opaque manner. You never see them, and only hear about results via the Facebook class. Under the hood, the Facebook class makes Graph API requests with the (not for public use) FBRequest class. This class is is basically a fancy NSURLConnection delegate. So to cancel the request, the member NSURLConnection just has to be told to cancel. Adding this method to FBRequest:

    // Add to FBRequest.h
    - (void)cancel;
    

    And...

    // Add to FBRequest.m
    - (void)cancel {
        [_connection cancel];
        [_connection release], _connection = nil;
    }
    

    Now, to expose an interface in the Facebook class to make use of the new method...

    // Add to Facebook.h
    - (void)cancelPendingRequest;  
    

    And...

    // Add to Facebook.m
    - (void)cancelPendingRequest {
        [_request cancel];
        [_request release], _request = nil;
    }
    

    That's all there is to it. The method above will cancel the most recent request, and you'll never hear from it again.

    0 讨论(0)
  • 2020-12-16 04:52

    Updated on 22/April/2012

    I update Matt's version with the most up-to-date Facebook iOS SDK. My Project is using ARC, but I include the non-ARC Facebook sources so that I can modify the codes. (Of Course, we need to set the "-fno-objc-arc" flag for Facebook source files). The tricky part is to prevent the memory leak, and I think I am doing it correctly. But When I test it in the instrument, I still see very small amount of memory leak. Fortunately, the details show that they are not related to these codes, so I just assume they are related to the app resource handling.

    Here is the code I implemented:

    // Add to Facebook.h
    - (void)cancelPendingRequest:(FBRequest *)releasingRequest; 
    

    And...

    // Add to Facebook.m
    - (void)cancelPendingRequest:(FBRequest *) releasingRequest{
        [releasingRequest.connection cancel];
        [releasingRequest removeObserver:self forKeyPath:requestFinishedKeyPath];
        [_requests removeObject:releasingRequest];    
    }
    

    And in your project which uses FBRequestDelegate

    // Declare this member or property to the .h file
    FBRequest * currentFbRequest;
    
    // Declare this method
    -(void)cancelFBRequest;
    

    And ...

    // In .m file
    AppDelegate * appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    // prepare your necessary request data and parameter ...
    currentFbRequest = [appDelegate.facebook requestWithGraphPath:@"/me/photos" 
        andParams:params 
        andHttpMethod:@"POST" 
        andDelegate:self];
    
    
    
    // Then in the method where you want to cancel
    AppDelegate * appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    [appDelegate.facebook cancelPendingRequest:currentFbRequest];
    currentFbRequest=nil;
    
    0 讨论(0)
提交回复
热议问题