2011-02-10 116 views
8

我偶尔需要取消FaceBook图形请求,但似乎在其API中没有取消或类似的方法。目前,由于我分配给请求的委托已被释放,有时会发生崩溃。有没有什么办法可以取消一次提交的图表请求?Facebook API - 如何取消图形请求

+0

你所说的 “图要求” 是什么意思?你能显示一些代码吗? – ifaour 2011-02-10 17:45:41

+0

有关最新的Facebook iOS SDK,请在底部查看我的答案。谢谢。 – 2012-04-21 17:18:02

回答

10

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

添加取消方法:
Facebook的请求是在一个不透明的方式进行。你永远不会看到它们,只能通过Facebook类听到结果。在引擎盖下,Facebook类使用Graph API请求(不用于公共使用)FBRequest类。这个类基本上是花式的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; 

And ...

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

这就是我所有s到它。上述方法将取消最近的请求,并且您再也不会听到它的声音。

+1

“请注意,您分配给该请求的委托不应该被解除分配,然后引用,因为该请求会保留委托。” [在最新的facebook-iphone-sdk中这不再是真的](http://stackoverflow.com/questions/4751982/does-facebook-class-of-iphone-facebook-sdk-have-cancel-method/6127405# 6127405) – albertamg 2011-05-25 16:25:56

0

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

-2

使卷曲调用该URL

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

我已经按照这里列出马特·威尔丁的做法,这是非常有用的,感谢马特。遗憾的是它并没有很多人会为我工作,所以我做了一些调整,现在,它的作品...还修订后的办法保持了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]; 

} 
4

更新于22月/ 4月/ 2012

我使用最新的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; 
1

试试这个,而不是使用的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]; 
} 
2

对于我们这些谁建的静态库和无法访问的实现文件,类别将是最好的一段路要走。

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

这里是说的类别。

// 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方法的第四行修复了这个问题。

0

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

在.h中添加了BOOL viewWillDisappear标志。在-(void) viewWillDisappear:中将该标志设置为YES。复位标志NO在-(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]; 
    } 
} 
1

由于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];