Facebook API - Как отменить запрос графика - PullRequest
8 голосов
/ 10 февраля 2011

Мне иногда нужно отменить запрос графа FaceBook, но, похоже, в их API нет метода отмены или подобного метода для этого. В настоящий момент иногда происходят сбои, поскольку делегат, назначенный мне для запроса, был освобожден. Можно ли отменить запрос графика после его отправки?

Ответы [ 9 ]

10 голосов
/ 15 февраля 2011

Я предполагаю, что вы говорите о проекте facebook-ios-sdk и об отсутствии метода отмены в Facebook.h.Я также заметил это и в конце концов решил добавить свой собственный метод отмены.Просто отметим, что делегат, который вы назначаете для запроса, никогда не должен быть delocloc'd и затем ссылаться на него, потому что запрос сохраняет делегата.См. этот похожий вопрос .Теперь, если вы действительно нуждаетесь в методе отмены по какой-то другой причине ...

Добавление метода отмены:
Запросы Facebook выполняются непрозрачным способом.Вы никогда не видите их, а слышите о результатах только через класс Facebook.Внутри класса Facebook запросы API-интерфейса Graph выполняются с классом 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;  

И ...

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

Это все, что нужно сделать.Приведенный выше метод отменяет самый последний запрос, и вы никогда не получите от него ответа.

4 голосов
/ 21 апреля 2012

Обновлено 22 апреля / 2012

Я обновляю версию Мэтта с помощью самой последней версии Facebook iOS SDK. Мой проект использует ARC, но я включаю не-ARC источники Facebook, чтобы я мог изменить коды. (Конечно, нам нужно установить флаг "-fno-objc-arc" для исходных файлов Facebook). Сложная задача - предотвратить утечку памяти, и я думаю, что делаю это правильно. Но когда я тестирую его в приборе, я все еще вижу очень небольшую утечку памяти. К счастью, детали показывают, что они не связаны с этими кодами, поэтому я просто предполагаю, что они связаны с обработкой ресурсов приложения.

Вот код, который я реализовал:

// 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 голосов
/ 25 ноября 2011

Я следовал описанному здесь подходу Мэтта Уилдинга, который был очень полезен, спасибо Мэтту.К сожалению, это не сработало для меня, поэтому я сделал некоторые изменения, и теперь это работает ... также этот пересмотренный подход не учитывает основные классы 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];

}
2 голосов
/ 15 августа 2012

Для тех из нас, кто создает статическую библиотеку и не имеет доступа к файлам реализации, лучше всего выбрать категорию.

Для тех из нас, кто не создавал статическую библиотеку, используякатегория также будет оптимальной, потому что вам не нужно изменять существующие файлы.

Вот эта категория.

// 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 решает эту проблему.

1 голос
/ 01 января 2013

Начиная с 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];
1 голос
/ 29 июня 2012

Попробуйте вместо использования 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];
}
0 голосов
/ 16 декабря 2012

У меня был сбой с предыдущим iOS Facebook SDK, который действовал в августе 2012 года, когда я переходил к другому представлению.Мое решение основано на ответе @staticfiction:

Добавлен флаг BOOL viewWillDisappear в .h.В -(void) viewWillDisappear: установите флаг ДА.Сбросить флаг в 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];
    }
}
0 голосов
/ 21 сентября 2011

Сделайте вызов CURL на этот URL

https://graph.facebook.com/REQUEST_ID?method=delete
0 голосов
/ 21 сентября 2011

В FBRequest.h мне пришлось add _delegate = nil;, потому что в моем случае делегат запроса больше не существовал (был отклонен), что вызвало сбой.

...