Ios Facebook API-如何取消图形请求

Ios Facebook API-如何取消图形请求,ios,facebook,facebook-graph-api,facebook-ios-sdk,Ios,Facebook,Facebook Graph Api,Facebook Ios Sdk,我偶尔需要取消FaceBook的图形请求,但在他们的API中似乎没有取消或类似的方法。目前,当我分配给请求的委托被解除分配时,有时会发生崩溃。有什么方法可以在提交后取消图形请求吗?我假设您正在谈论facebook ios sdk项目,以及facebook.h中缺少取消方法。我也注意到了这一点,并最终决定添加我自己的cancel方法。需要注意的是,您分配给请求的委托永远不应该被解除锁定然后被引用,因为请求保留了委托。看见现在,如果你发现自己真的因为其他原因需要取消方法 添加取消方法: Facebo

我偶尔需要取消FaceBook的图形请求,但在他们的API中似乎没有取消或类似的方法。目前,当我分配给请求的委托被解除分配时,有时会发生崩溃。有什么方法可以在提交后取消图形请求吗?

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

添加取消方法:
Facebook的请求是以不透明的方式提出的。你永远不会看到它们,只会通过
Facebook
类听到结果。在引擎盖下,
Facebook
类使用(不供公众使用)
FBRequest
类发出Graph API请求。这个类基本上是一个奇特的
NSURLConnection
委托。因此,要取消请求,只需告诉成员
NSURLConnection
取消即可。将此方法添加到FBRequest:

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

// Add to FBRequest.m
- (void)cancel {
    [_connection cancel];
    [_connection release], _connection = nil;
}
// Add to Facebook.m
- (void)cancelPendingRequest {
    [_request cancel];
    [_request release], _request = nil;
}
// Add to Facebook.m
- (void)cancelPendingRequest:(FBRequest *) releasingRequest{
    [releasingRequest.connection cancel];
    [releasingRequest removeObserver:self forKeyPath:requestFinishedKeyPath];
    [_requests removeObject:releasingRequest];    
}
现在,要在Facebook类中公开一个接口以使用新方法

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

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

就这些。上述方法将取消最近的请求,您将再也听不到它的消息。

FBRequest.h
中,我不得不添加\u delegate=nil因为在我的例子中,请求委托不再存在(它被解除),这导致了崩溃。

对此URL进行CURL调用

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

我遵循了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];

}

更新日期:2012年4月22日

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

以下是我实现的代码:

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

// Add to FBRequest.m
- (void)cancel {
    [_connection cancel];
    [_connection release], _connection = nil;
}
// Add to Facebook.m
- (void)cancelPendingRequest {
    [_request cancel];
    [_request release], _request = nil;
}
// 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;

请尝试此操作,而不是使用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];
}

对于我们这些构建静态库而无法访问实现文件的人来说,分类将是最好的方法

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

这里是所说的类别

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

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

添加的
BOOL视图将在.h中消失
标志。在
-(void)视图中将消失:
将标志设置为“是”。在
-(void)视图中将标志重置为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];
    }
}

自SDK 3.1以来,它非常简单,因为它返回一个对象,该对象具有一个
-(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];

“图形请求”是什么意思?你能展示一些代码吗?有关最新的Facebook iOS SDK,请参见底部的我的答案。谢谢。“请注意,您分配给请求的代理永远不应该被解除锁定然后被引用,因为请求保留了代理。”@albertamg,这是个好消息。当代理被保留时,我总是感到恶心。有关最新的Facebook iOS SDK,请参阅底部的我的答案。谢谢。当收到正常响应时,可能需要取消以前的PerformRequestswithTarget