2011-02-10 18 views
8

Occasionalmente ho bisogno di cancellare una richiesta di faceBook, ma sembra che non ci siano cancellazioni o metodi simili nelle loro API per farlo. Al momento, a volte si verificano arresti anomali poiché il delegato che ho assegnato alla richiesta è stato deallocato. C'è un modo per cancellare una richiesta di grafico una volta inviata per favore?Facebook API - Come cancellare Graph Request

+0

Che cosa si intende per "richiesta Graph"? puoi mostrare un po 'di codice? – ifaour

+0

Per l'SDK di Facebook SD più aggiornato, vedere la mia risposta in fondo. Grazie. –

risposta

10

Suppongo che tu stia parlando del progetto facebook-ios-sdk e della mancanza di un metodo di annullamento in Facebook.h. Ho notato anche questo, e alla fine ho deciso di aggiungere il mio metodo di annullamento. Solo per notare, il delegato che si assegna alla richiesta non dovrebbe mai essere dealloc'd e quindi referenziato, poiché la richiesta mantiene il delegato. Vedi this similar question. Ora, se vi trovate davvero bisogno di un metodo di annullare per qualche altra ragione ...

Aggiunta di un metodo di cancellazione:
richieste di Facebook sono realizzati in maniera non chiara. Non li vedi mai e ascolti solo i risultati tramite la classe Facebook. Sotto il cofano, la classe Facebook effettua richieste API Graph con la classe FBRequest (non per uso pubblico). Questa classe è fondamentalmente un simpatico delegato NSURLConnection. Quindi, per annullare la richiesta, il membro NSURLConnection deve solo essere detto a cancel. L'aggiunta di questo metodo per FBRequest:

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

E ...

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

Ora, di esporre un'interfaccia nella classe Facebook per utilizzare il nuovo metodo ...

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

E ...

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

Questo è tutto i s ad esso. Il metodo sopra cancellerà la richiesta più recente e non ne sentirai più.

+1

"È sufficiente notare che il delegato che si assegna alla richiesta non deve mai essere deallocato e quindi referenziato, poiché la richiesta mantiene il delegato." [Questo non è più vero nel nuovissimo facebook-iphone-sdk] (http://stackoverflow.com/questions/4751982/does-facebook-class-of-iphone-facebook-sdk-have-cancel-method/6127405# 6127405) – albertamg

+1

@albertamg, questa è una buona notizia. Mi sono sempre sentito icky quando i delegati vengono trattenuti. –

+0

Per l'SDK iOS di Facebook più aggiornato, vedere la mia risposta in fondo. Grazie. –

0

In FBRequest.h, ho dovuto add _delegate = nil; perché nel mio caso, il delegato della richiesta non esisteva più (è stato chiuso) che ha causato un arresto anomalo.

-2

Effettuare una chiamata CURL a questo URL

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

ho seguito l'approccio di Matt Wilding elencati qui, che è stato molto utile, grazie Matt. Purtroppo che non ha ancora abbastanza lavoro per me, così ho fatto alcune modifiche e ora funziona ... anche questo approccio rivisto tiene fuori delle classi di base di 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

Aggiornato il 22/Aprile/2012

Aggiorno la versione di Matt con l'SDK di Facebook più aggiornato. Il mio progetto utilizza ARC, ma includo le fonti di Facebook non ARC in modo che possa modificare i codici. (Ovviamente, dobbiamo impostare il flag "-fno-objc-arc" per i file di origine di Facebook). La parte difficile è prevenire la perdita di memoria e penso che lo stia facendo correttamente. Ma quando lo provo nello strumento, vedo ancora una piccola quantità di perdita di memoria. Fortunatamente, i dettagli mostrano che non sono correlati a questi codici, quindi presumo solo che siano correlati alla gestione delle risorse dell'app.

Ecco il codice che ho implementato:

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

E ...

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

E nel progetto che utilizza FBRequestDelegate

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

// Declare this method 
-(void)cancelFBRequest; 

E ...

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

Prova questa invece di utilizzare 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

Probabilmente è necessario "cancelPreviousPerformRequestsWithTarget" quando arrivano le normali risposte. – ohho

2

Per quelli di noi che costruiscono la libreria statica e sono in grado di accedere ai file di implementazione, una categoria sarebbe il modo migliore per andare.

Per quelli di noi che non hanno creato la libreria statica, l'utilizzo di una categoria sarebbe ottimale anche perché non è necessario modificare i file esistenti.

Qui è detta categoria.

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

@interface Facebook (Facebook_cancel) 

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

- (void)cancelAllRequests; 

@end 

E poi il file .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 

Per coloro che utilizzano qualsiasi altra risposta, si stanno causando una perdita di memoria. L'SDK di Facebook ti avviserà tramite NSLog che non hai rimosso un osservatore. La quarta riga nel metodo cancelAllRequests risolve questo problema.

0

Si è verificato un arresto anomalo con il precedente SDK iOS di iOS valido nell'agosto 2012 ogni volta che ho navigato su un'altra vista. La mia soluzione si basa sulla risposta @staticfiction:

Aggiunto BOOL viewWillDisappear flag in .h. In -(void) viewWillDisappear: imposta il flag su SÌ. Reimpostare bandiera 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]; 
    } 
} 
1

Da SDK 3.1, è molto facile, come startWithCompletionHandler: restituisce un oggetto FBRequestConnection, che ha un metodo -(void)cancel;.

Ad esempio:

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