2011-02-10 11 views
8

Czasami muszę anulować żądanie wykresu FaceBook, ale wydaje się, że nie ma w nim żadnego odwołania ani podobnej metody. W tej chwili zdarzają się awarie, ponieważ delegat przydzielony do żądania został zwolniony. Czy istnieje jakiś sposób anulowania żądania wykresu po przesłaniu?Facebook API - Jak anulować żądanie wykresu

+0

Co masz na myśli przez "wniosek Graph"? czy możesz pokazać kod? – ifaour

+0

Najbardziej aktualny pakiet SDK na Facebooku iOS znajduje się na dole. Dzięki. –

Odpowiedz

10

Zakładam, że mówisz o projekcie facebook-ios-sdk i braku metody anulowania w Facebook.h. Zauważyłem to również i ostatecznie zdecydowałem się dodać własną metodę anulowania. Pamiętaj tylko, że delegat przypisany do żądania nie powinien nigdy być dealloc'd, a następnie odwoływać się, ponieważ żądanie zachowuje delegata. Zobacz this similar question. Teraz, jeśli okaże się naprawdę potrzebują anulować metody z innego powodu ...

Dodanie metody Cancel:
Facebook wnioski są w nieprzezroczystej sposób. Nigdy ich nie widzisz i słyszysz tylko o wynikach za pośrednictwem klasy Facebook. Pod maską, klasa Facebook tworzy żądania interfejsu API Graph z klasą (nie do użytku publicznego) FBRequest. Ta klasa jest po prostu fantazyjnym delegatem NSURLConnection. Aby anulować prośbę, członek NSURLConnection musi zostać poinformowany o cancel. Dodanie tej metody FBRequest:

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

I ...

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

Teraz, aby wystawiać interfejsu w klasie Facebooku, aby skorzystać z nowej metody ...

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

I ...

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

To wszystko tam do tego. Powyższa metoda anuluje ostatnią prośbę i nigdy więcej nie usłyszysz od niej.

+1

"Pamiętaj tylko, że delegat przypisany do żądania nie powinien nigdy być dealloc'd, a następnie odwoływać się, ponieważ żądanie zachowuje delegata." [To nie jest już prawdą w najnowszym facebook-iphone-sdk] (http://stackoverflow.com/questions/4751982/does-facebook-class-of-iphone-facebook-sdk-have-cancel-method/6127405# 6127405) – albertamg

+1

@albertamg, To dobra wiadomość. Zawsze czułem się nieswojo, gdy delegaci są zatrzymywani. –

+0

Najbardziej aktualny pakiet SDK na Facebooku iOS znajduje się na dole. Dzięki. –

0

W FBRequest.h, musiałem add _delegate = nil;, ponieważ w moim przypadku delegat żądania już nie istniał (został zwolniony), co spowodowało awarię.

-2

Nawiązywanie połączenia CURL do tego URL

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

Mam następnie podejście Matt Wildinga na tej liście, co było bardzo przydatne, dzięki Matt. Niestety nie zrobił dość pracy dla mnie, więc zrobiłem kilka poprawek i teraz to działa ... także to poprawione podejście utrzymuje się z klas podstawowych 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

Zaktualizowano 22/kwietnia/2012

Aktualizuję wersję Matta za pomocą najnowszego pakietu SDK na Facebooku iOS. Mój projekt korzysta z ARC, ale dołączam źródła Facebooka spoza ARC, dzięki czemu mogę modyfikować kody. (Oczywiście, musimy ustawić flagę "-fno-objc-arc" dla plików źródłowych Facebooka). Najtrudniejszą częścią jest zapobieganie wyciekom pamięci i myślę, że robię to poprawnie. Ale kiedy testuję to na instrumencie, wciąż widzę bardzo małą ilość wycieku pamięci. Na szczęście szczegóły pokazują, że nie są one powiązane z tymi kodami, więc po prostu zakładam, że są one powiązane z obsługą zasobów aplikacji.

Oto kod I wdrożone:

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

I ...

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

A w projekcie, który wykorzystuje FBRequestDelegate

// Declare this member or property to the .h file 
FBRequest * currentFbRequest; 

// Declare this method 
-(void)cancelFBRequest; 

I ...

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

Spróbuj to zamiast używać 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

Prawdopodobnie trzeba "cancelPreviousPerformRequestsWithTarget", gdy pojawią się normalne odpowiedzi. – ohho

2

Dla tych z nas, którzy zbudować bibliotekę statyczną i nie są w stanie uzyskać dostęp do plików wykonawczych, kategoria byłaby najlepsza droga.

Dla tych z nas, którzy nie zbudowali biblioteki statycznej, użycie kategorii będzie również optymalne, ponieważ nie trzeba modyfikować istniejących plików.

Oto kategoria.

// Facebook+Cancel.h 
#import "Facebook.h" 

@interface Facebook (Facebook_cancel) 

- (void)cancelPendingRequest:(FBRequest *)releasingRequest; 

- (void)cancelAllRequests; 

@end 

a następnie plik .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 

Dla tych, używając innej odpowiedzi, jesteś powodując wyciek pamięci. Facebook SDK ostrzeże Cię przez NSLog, że nie usunąłeś obserwatora. Czwarta linia w metodzie cancelAllRequests rozwiązuje ten problem.

0

Miałem awarię z poprzednim pakietem SDK dla systemu iOS, który był ważny w sierpniu 2012 r., Gdy nawigowałem do innego widoku. Moje rozwiązanie oparte jest na odpowiedzi na pytanie o statusie statycznym:

Dodano flagę BOOL viewWillDisappear w .h. W -(void) viewWillDisappear: ustaw flagę na YES. Wyzerować flagę NO w -(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

Ponieważ SDK 3.1, jest to bardzo proste, jak startWithCompletionHandler: zwraca FBRequestConnection obiekt, który ma metodę -(void)cancel;.

Na przykład:

// 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]; 
Powiązane problemy