2011-01-20 12 views
9

Esiste comunque la possibilità di annullare la richiesta in sospeso di un oggetto di Facebook?La classe Facebook dell'iPhone Facebook SDK ha il metodo di annullamento?

Non riesco a trovare alcun metodo in Facebook.h o un modo per accedere all'oggetto sottostante NSURLConnection. Se torno indietro sulla barra di navigazione e la loro è una richiesta Facebook asincrona in sospeso, la richiesta tenta di inviare un messaggio a un deallocated view una volta che la risposta è arrivata, causando l'arresto anomalo dell'applicazione.

risposta

7

EDIT Come sottolineato nella risposta di Tim a questa domanda, questa informazione è ormai obsoleto con le più recenti versioni del Facebook SDK per iOS.

Non esiste alcun modo per annullare una richiesta in sospeso. Tuttavia, questo non dovrebbe rovinare la tua app.

La classe Facebook utilizza la classe FBRequest sotto il cofano per rendere tutte le sue richieste API REST o Graph e questa è la classe che termina con un riferimento alla vista (controller?) Come proprietà delegato. Guardando l'intestazione per FBRequest:

@interface FBRequest : NSObject { 
    id<FBRequestDelegate> _delegate; 
    NSString*    _url; 
    NSString*    _httpMethod; 
    NSMutableDictionary* _params; 
    NSURLConnection*  _connection; 
    NSMutableData*  _responseText; 
} 

@property(nonatomic,assign) id<FBRequestDelegate> delegate; 

L'attributo di assegnazione nella dichiarazione di proprietà fa sembrare che memorizza debole-ref alla classe, ma poi in FBRequest.m:

+ (FBRequest *)getRequestWithParams:(NSMutableDictionary *) params 
         httpMethod:(NSString *) httpMethod 
          delegate:(id<FBRequestDelegate>) delegate 
         requestURL:(NSString *) url { 
    FBRequest* request = [[[FBRequest alloc] init] autorelease]; 
    request.delegate  = [delegate retain]; // <- It's retained! (Comment mine) 
    request.url   = [url retain]; 
    request.httpMethod = [httpMethod retain]; 
    request.params  = [params retain]; 
    request.connection = nil; 
    request.responseText = nil; 

    return request; 
} 

E ' mantiene chiaramente il delegato. Quindi, nel normale flusso della tua applicazione, quando pensi che il tuo controller di visualizzazione debba essere deallocato dopo essere stato prelevato dallo stack di navigazione, lo FBRequest ha assicurato che sarà ancora vivo per ricevere la risposta assumendone la proprietà.

Questo fa sembrare che potresti avere altri problemi di gestione della memoria altrove nell'app.

+0

Grazie, mi hai salvato la giornata. –

9

Per chiunque incontri questa domanda, sembra che l'osservazione di Matt non si applichi al più recente facebook-iphone-sdk. I parametri non sono più esplicitamente mantenuti nel metodo relativo:

+ (FBRequest *)getRequestWithParams:(NSMutableDictionary *) params 
         httpMethod:(NSString *) httpMethod 
          delegate:(id<FBRequestDelegate>) delegate 
         requestURL:(NSString *) url { 

    FBRequest* request = [[[FBRequest alloc] init] autorelease]; 
    request.delegate = delegate; 
    request.url = url; 
    request.httpMethod = httpMethod; 
    request.params = params; 
    request.connection = nil; 
    request.responseText = nil; 

Quindi la gestione della memoria per il delegato ricade sulla dichiarazione di proprietà nel file .h:

@property(nonatomic,assign) id<FBRequestDelegate> delegate; 

Ciò significa che un incidente è ora possibile poiché l'oggetto delegato può essere deallocato prima che FBRequest sia completato.

Aggiornamento:

Una possibile soluzione è suggerita in this domanda per consentire la cancellazione di FBRequests in sospeso.

Aggiornamento 2:

Per evitare un arresto nel caso in cui il delegato viene deallocato prima che finisce il FBRequest, è necessario annullare la connessione del FBRequest attivo come si DEALLOCATE il delegato (che è fondamentalmente ciò che suggerisce Matt nella domanda collegata). Tuttavia (non sono sicuro che sia nuovo), puoi farlo direttamente su FBRequest poiché espone la sua proprietà NSURLConnection.Quindi, se si mantiene l'oggetto FBRequest in una proprietà:

@property (nonatomic, retain) FBRequest *myRequest; 

e salvare l'oggetto di richiesta al momento della chiamata:

self.myRequest = [facebookObj requestWithGraphPath:@"me" andDelegate:self]; 

si può pulire tutto nel vostro dealloc:

- (void)dealloc 
{ 
if(myRequest) { 
    [[myRequest connection] cancel]; 
    [[myRequest release]; 
    } 

    ... 

    [super dealloc]; 
} 

Ovviamente, dovresti probabilmente rilasciare e annullare la proprietà FBRequest nei metodi delegati dopo aver elaborato la risposta.

+1

C'è un [problema aperto] (https://github.com/facebook-ios-sdk/issues/220) su questo. – albertamg

+0

Commento di @ user1526896: È necessario aggiungere 'myRequest.delegate = nil;' per evitare un arresto anomalo dell'applicazione. – Damon

Problemi correlati