2014-09-27 12 views
5

Sto cercando di aggiornare un nodo Firebase nella transazione, cose semplici. A seguire il doc:Firebase come controllare il successo o il fallimento della transazione?

https://www.firebase.com/docs/ios/guide/saving-data.html

Firebase* upvotesRef = [[Firebase alloc] initWithUrl: @"https://docs-examples.firebaseio.com/web/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes"]; 

[upvotesRef runTransactionBlock:^FTransactionResult *(FMutableData *currentData) { 
    NSNumber *value = currentData.value; 
    if (currentData.value == [NSNull null]) { 
     value = 0; 
    } 
    [currentData setValue:[NSNumber numberWithInt:(1 + [value intValue])]]; 
    return [FTransactionResult successWithValue:currentData]; 
}]; 

La grande domanda è: Come faccio a controllare l'esito di tale operazione (successo/fail)? Vorrei fare alcune modifiche all'interfaccia utente dipende dal risultato di esso.

C'è un altro metodo nel documento SDK che sembra avere una richiamata, ma non ha spiegato quale valore dovrei controllare. E dice qualcosa sul metodo potrebbe essere eseguito più volte. Come posso assicurarmi quando dà il risultato "finale"? https://www.firebase.com/docs/ios-api/Classes/Firebase.html#//api/name/runTransactionBlock:andCompletionBlock:

Scusa, sono un principiante che lo stile Apple non si riunisce senza alcuni esempi.

risposta

10

Se si solo si desidera attendere il valore finale, runTransactionBlock:andCompletionBlock: è il metodo che si desidera esaminare. Ecco qualche esempio di codice:

[upvotesRef runTransactionBlock:^FTransactionResult *(FMutableData *currentData) { 
    NSNumber *value = currentData.value; 
    if (currentData.value == [NSNull null]) { 
     value = 0; 
    } 
    [currentData setValue:[NSNumber numberWithInt:(1 + [value intValue])]]; 
    return [FTransactionResult successWithValue:currentData]; 
} andCompletionBlock:^(NSError *error, BOOL committed, FDataSnapshot *snapshot) { 
    if (error) { 
     NSLog(@"Error: %@", error); 
    } 
    if (committed) { 
     NSLog(@"Data committed"); 
    } 
    NSLog(@"Final Value: %@", snapshot.value); 
}]; 

Questo ultimo valore c'è, snapshot.value è dove è possibile ottenere il valore finale. È lo stesso tipo di FDataSnapshot che ottieni se usi observeEventType:withBlock:

Se qualcosa va storto, riceverai un error.

Se i dati vengono confermati, committed sarà SÌ. Se hai restituito [FTransactionResult abort] nel blocco di transazioni anziché [FTransactionResult successWithValue:], il numero committed sarà NO.

Ciò significa che se si legge il contatore su 4 e si tenta di aggiornarlo. Potresti provare ad aggiornare il contatore nello stesso momento in cui lo fa qualcun altro. Se il tuo entrasse per primo, il numero snapshot.value sarà 5. Se l'aggiornamento dell'altro interviene prima di farlo, il numero snapshot.value sarà 6.

Probabilmente volevi arrivare fino a 6, indipendentemente da chi avanzava per primi. Per fare ciò, è necessario aggiungere un osservatore. Il codice per che potrebbe essere simile:

[upvotesRef observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) { 
    NSLog(@"New Value: %@", snapshot.value); 
}]; 

Con questo, non c'è bisogno il blocco di completamento per scoprire il valore finale perché ogni volta che i blocchi di transazione, il blocco osservatore fuoco. Nello scenario di esempio sopra, sparerebbe una volta per 5 e una volta per 6, non importa chi ha alzato per primo. Hai bisogno del blocco di completamento se vuoi scoprire se la tua particolare transazione ha avuto successo e non solo quale valore si trova in quella posizione ora.

E, per essere completo, esiste un altro metodo chiamato runTransactionBlock:andCompletionBlock:withLocalEvents:. Se anche altri scrivono nello stesso percorso, il blocco della transazione può essere eseguito più volte. Questo succede se scopre che è in esecuzione su dati non aggiornati. Quando viene eseguito correttamente su nuovi dati, chiamerà il blocco di completamento. Tuttavia, scoprirai che ogni volta che viene eseguito, si spara qualsiasi blocco di osservatore in quella posizione. Se si non si desidera che ciò accada, è necessario passare NO a withLocalEvents:. Firebase attiverà gli eventi in quella posizione ogni volta che una scrittura confermata passa, ma le scritture temporanee della transazione locale, che non sono confermate, non lo faranno.

Guardando indietro all'esempio in cui tu e un'altra persona provate a fare lo stesso allo stesso tempo. Per impostazione predefinita, l'osservatore si avvierà non appena si tenta di aggiornare il conteggio da 4 a 5. La transazione effettiva potrebbe non riuscire perché qualcun altro ha spinto il conteggio upvote da 4 a 5 allo stesso tempo. Il tuo blocco di transazioni verrebbe quindi eseguito di nuovo con i nuovi dati, 5, e vedrai che dovrebbe spingere il conteggio a 6. Con gli eventi locali impostati su NO, l'osservatore si attiverà dopo che il server ti farà sapere qualcun altro ha spinto il conteggio dell'upvole da 4 a 5, e non quando si tenta di aggiornare il conteggio da 4 a 5.

Questo non è un grosso problema con qualcosa di semplice come upvotes dove tutti stanno solo incrementando, ma se si potrebbe potenzialmente spingere dati diversi da altri gli utenti, qualsiasi osservatore nel luogo può vedere i dati saltare prima di stabilirsi definitivamente.

+4

Questa risposta deve essere aggiunta al documento API Firebase ... non scherzo. – Reed

+1

Onestamente, lo spiega perfettamente. Cheers brothers –

+0

@katfang se potessi scrivere l'equivalente per Swift, sarebbe molto utile. Grazie molto – bibscy

Problemi correlati