【问题标题】:Facebook API - How to cancel Graph RequestFacebook API - 如何取消图形请求
【发布时间】:2011-06-24 22:34:19
【问题描述】:

我偶尔需要取消 FaceBook 图形请求,但他们的 API 中似乎没有取消或类似的方法来执行此操作。目前,由于我分配给请求的委托已被释放,有时会发生崩溃。请问有什么方法可以取消提交后的图表请求吗?

【问题讨论】:

  • “图表请求”是什么意思?你能显示一些代码吗?
  • 最新的Facebook iOS SDK,请在底部查看我的回答。谢谢。

标签: ios facebook facebook-graph-api facebook-ios-sdk


【解决方案1】:

我假设您正在谈论 facebook-ios-sdk 项目,以及 Facebook.h 中缺少取消方法。我也注意到了这一点,最终决定添加我自己的取消方法。请注意,您分配给请求的委托不应该被释放然后引用,因为请求保留了委托。见this similar question。现在,如果您发现自己出于其他原因确实需要取消方法...

添加取消方法:
Facebook 请求以不透明的方式发出。您永远不会看到它们,只能通过 Facebook 类听到结果。在后台,Facebook 类使用(不供公众使用)FBRequest 类发出 Graph API 请求。这个类基本上是一个花哨的NSURLConnection 代表。因此,要取消请求,只需将成员NSURLConnection 告知cancel。将此方法添加到 FBRequest:

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

还有……

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

现在,在 Facebook 类中公开一个接口以使用新方法...

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

还有……

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

仅此而已。上述方法将取消最近的请求,您将永远不会再收到它的消息。

【讨论】:

  • "请注意,您分配给请求的委托不应被解除分配然后被引用,因为请求保留了委托。" This is no longer true in the newest facebook-iphone-sdk
  • @albertamg,这是个好消息。保留代表时我总是感到恶心。
  • 关于最新的 Facebook iOS SDK,请在底部查看我的回答。谢谢。
【解决方案2】:

我遵循了此处列出的 Matt Wilding 的方法,这非常有用,感谢 Matt。不幸的是,它对我来说不太奏效,所以我做了一些调整,现在它可以工作了......而且这种修改后的方法也远离了核心 facebook 类......

//in .h define an FBRequest property
@property (nonatomic, retain) FBRequest * pendingFBRequest;

//in .m when making your request, store it in your FBRequest property
pendingFBRequest = [facebook requestWithGraphPath:@"me/feed"
                                        andParams:params
                                    andHttpMethod:@"POST"
                                      andDelegate:self];

//create a timer for your timeout
pendingFacebookActionTimer = [NSTimer scheduledTimerWithTimeInterval:15.0 target:self selector:@selector(onPendingFacebookActionTimeout) userInfo:nil repeats:NO];

//cancel the action on the timeout's selector method
-(void)onPendingFacebookActionTimeout {

    [pendingFBRequest.connection cancel];

}

【讨论】:

    【解决方案3】:

    2012 年 4 月 22 日更新

    我使用最新的 Facebook iOS SDK 更新了 Matt 的版本。我的项目正在使用 ARC,但我包含了非 ARC Facebook 资源,以便我可以修改代码。 (当然,我们需要为 Facebook 源文件设置“-fno-objc-arc”标志)。棘手的部分是防止内存泄漏,我认为我做得对。但是当我在仪器中测试它时,我仍然看到非常少量的内存泄漏。幸运的是,细节表明它们与这些代码无关,所以我只是假设它们与应用程序资源处理有关。

    这是我实现的代码:

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

    还有……

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

    在您使用 FBRequestDelegate 的项目中

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

    还有……

    // 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;
    

    【讨论】:

      【解决方案4】:

      对于我们这些构建静态库但无法访问实现文件的人来说,类别将是最好的选择。

      对于我们这些没有构建静态库的人来说,使用类别也是最佳选择,因为您不需要修改现有文件。

      这里是说的类别。

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

      然后是.m文件

      // 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
      

      对于那些使用任何其他答案的人,您正在导致内存泄漏。 Facebook SDK 将通过 NSLog 警告您尚未删除观察者。 cancelAllRequests 方法中的第四行修复了这个问题。

      【讨论】:

        【解决方案5】:

        试试这个而不是使用 NSTimer:

        FBRequest *fbRequest = [facebook requestWithGraphPath:@"me" andDelegate:self];
        [self performSelector:@selector(fbRequestTimeout:) withObject:fbRequest afterDelay:30];
        
        - (void)fbRequestTimeout:(FBRequest *)fbRequest
        {
            [fbRequest.connection cancel];
            [fbRequest setDelegate:nil];
        }
        

        【讨论】:

        • 正常回复进来时可能需要cancelPreviousPerformRequestsWithTarget
        【解决方案6】:

        从 SDK 3.1 开始,这很容易,因为 startWithCompletionHandler: 返回一个 FBRequestConnection 对象,它有一个 -(void)cancel; 方法。

        例如:

        // In interface or .h definitions:
        @property (strong, nonatomic) FBRequest             *fBRequest;
        @property (strong, nonatomic) FBRequestConnection   *fbConnection;
        
        // when needed in class (params should be set elsewhere, this is just an example):
        self.fBRequest = [[FBRequest alloc] initWithSession:[FBSession activeSession] graphPath:@"me/photos" parameters:params HTTPMethod:@"POST"];
        self.fbConnection = [self.fBRequest startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error){
            NSLog(@"Publish complete, error: %d", error.code);
        }];
        
        // now, to cancel anywhere in the class, just call:
        [self.fbConnection cancel];
        

        【讨论】:

          【解决方案7】:

          FBRequest.h,我不得不add _delegate = nil;,因为在我的情况下,请求委托不再存在(它被解除),这导致了崩溃。

          【讨论】:

            【解决方案8】:

            当我导航到另一个视图时,我在 2012 年 8 月有效的以前的 iOS Facebook SDK 中遇到了崩溃。我的解决方案基于@staticfiction 响应:

            在 .h 中添加了 BOOL viewWillDisappear 标志。在-(void) viewWillDisappear: 中将标志设置为YES。将-(void) viewDidAppear:中的标志重置为NO

            //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];
                }
            }
            

            【讨论】:

              【解决方案9】:

              对该 URL 进行 CURL 调用

              https://graph.facebook.com/REQUEST_ID?method=delete
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多