Facebook API - 如何取消图形请求

发布于 2024-10-17 02:55:19 字数 103 浏览 3 评论 0原文

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

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 the delegate I assigned to the request has been deallocated. Is there any way to cancel a graph request once submitted please?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

那支青花 2024-10-24 02:55:19

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

添加取消方法:
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;
}

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

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

并且...

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

这就是全部内容。上述方法将取消最近的请求,您将永远不会再收到它的消息。

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.

迟到的我 2024-10-24 02:55:19

我遵循了这里列出的 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];

}

I've followed Matt Wilding's approach listed here, which was very useful, thanks Matt. Unfortunately it didnt quite work for me, so I made some tweaks and now it works... also this revised approach keeps out of the core facebook classes...

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

}
秉烛思 2024-10-24 02:55:19

更新于 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;

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;
我不吻晚风 2024-10-24 02:55:19

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

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

这里说的是类别。

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

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.

口干舌燥 2024-10-24 02:55:19

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

Try this instead of using 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];
}
季末如歌 2024-10-24 02:55:19

从 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];

Since SDK 3.1, it's very easy, as startWithCompletionHandler: returns a FBRequestConnection object, which has a -(void)cancel; method.

For example:

// 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];
拧巴小姐 2024-10-24 02:55:19

FBRequest.h中,我必须add _delegate = nil;,因为在我的例子中,请求委托不再存在(它被解雇),这导致了崩溃。

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.

谢绝鈎搭 2024-10-24 02:55:19

每当我导航到另一个视图时,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];
    }
}

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];
    }
}
将军与妓 2024-10-24 02:55:19

对此 URL 进行 CURL 调用

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

Make a CURL call to this URL

https://graph.facebook.com/REQUEST_ID?method=delete
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文