If you just想要等待最终值,runTransactionBlock:andCompletionBlock:
是您想要查看的方法。这是一些示例代码:
[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);
}];
那里的最后一个值,snapshot.value
是你可以获得最终价值的地方。这是同一种类型FDataSnapshot
如果你使用你会得到observeEventType:withBlock:
如果出现问题,您将得到一个error
.
如果您的数据已提交,committed
将会是“是”。如果你回来了[FTransactionResult abort]
在你的交易块中而不是[FTransactionResult successWithValue:]
, committed
将会是NO。
这意味着,如果您读取 4 处的计数器并尝试更新它。您可能会尝试与其他人同时更新计数器。如果你先进去的话snapshot.value
将为 5。如果其他人的更新先于您到达,则snapshot.value
将是 6。
无论谁先投票,您可能都希望达到 6 分。为此,您需要添加一个观察者。其代码可能如下所示:
[upvotesRef observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
NSLog(@"New Value: %@", snapshot.value);
}];
有了这个,你就不用need完成块找出最终值,因为每次事务阻塞时,观察者块都会触发。在上面的示例场景中,无论谁先投票,它都会为 5 触发一次,为 6 触发一次。如果您想了解您的特定交易是否成功,而不仅仅是该位置现在的价值,那么您确实需要完成块。
而且,为了完整起见,还有一种方法称为runTransactionBlock:andCompletionBlock:withLocalEvents:
。如果其他人也写入同一位置,则事务块可能会运行多次。如果它发现它正在陈旧的数据上运行,就会发生这种情况。当它在新数据上成功运行时,它将调用完成块。但是,您会发现每次运行时,它都会触发该位置的任何观察者块。如果你don't希望这种情况发生,你应该将 NO 传递给withLocalEvents:
。每当经过确认的写入时,您的 Firebase 都会在该位置触发事件,但本地事务的未经确认的临时写入则不会。
回顾一下您和另一个人同时尝试投票的示例。默认情况下,一旦您尝试将计数从 4 更新到 5,观察者就会触发。实际事务可能会失败,因为其他人同时将赞成计数从 4 推到了 5。然后,您的事务块将使用新数据 5 再次运行,并看到它应该将计数推至 6。当本地事件设置为“否”时,观察者将在服务器让您知道其他人将赞成计数从 4 推高后触发到 5,而不是当您尝试将计数从 4 更新到 5 时。
对于像投票这样简单的事情来说,这并不是什么大问题,每个人都只是在增加,但如果您可能会从其他用户推送不同的数据,那么该位置的任何观察者都可能会看到数据在最终稳定之前跳跃。