2014-09-27 14 views
5

Tôi cố gắng để cập nhật một nút căn cứ hỏa lực trong giao dịch, công cụ đơn giản. Theo doc:Firebase cách kiểm tra giao dịch thành công hay thất bại?

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

Câu hỏi lớn là: Làm thế nào để kiểm tra kết quả của giao dịch này (thành công/thất bại)? Tôi muốn thực hiện một số thay đổi giao diện người dùng phụ thuộc vào kết quả của nó.

Có một phương pháp khác trong tài liệu SDK dường như có gọi lại nhưng không giải thích được giá trị nào tôi nên kiểm tra. Và nó nói một cái gì đó về phương pháp này có thể chạy nhiều lần. Làm thế nào để đảm bảo khi nó mang lại kết quả "cuối cùng"? https://www.firebase.com/docs/ios-api/Classes/Firebase.html#//api/name/runTransactionBlock:andCompletionBlock:

Xin lỗi tôi là người mới bắt đầu rằng tài liệu theo phong cách táo thực sự không đến với nhau mà không có một số ví dụ.

Trả lời

10

Nếu bạn chỉ muốn đợi giá trị cuối cùng, runTransactionBlock:andCompletionBlock: là phương pháp bạn muốn xem. Dưới đây là một số mã mẫu:

[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); 
}]; 

Giá trị cuối cùng đó, snapshot.value là nơi bạn có thể nhận giá trị cuối cùng. Đó là cùng loại FDataSnapshot mà bạn nhận được nếu bạn sử dụng observeEventType:withBlock:

Nếu xảy ra sự cố, bạn sẽ nhận được error.

Nếu dữ liệu của bạn được cam kết, committed sẽ YES. Nếu bạn trở [FTransactionResult abort] trong khối giao dịch của bạn thay vì [FTransactionResult successWithValue:], committed sẽ NO.

Điều này có nghĩa, nếu bạn đọc truy cập vào 4 và cố gắng cập nhật nó. Bạn có thể thử cập nhật bộ đếm cùng lúc với người khác. Nếu bạn nhận được trong đầu tiên, snapshot.value sẽ là 5. Nếu bản cập nhật của người khác nhận được trước khi bạn làm, các snapshot.value sẽ là 6.

Bạn có thể muốn nhận được lên đến 6 không có vấn đề người upvoted đầu tiên. Để làm điều này, bạn cần phải thêm một người quan sát. Mã cho rằng có thể trông giống như:

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

Với điều này, bạn không cần khối hoàn thành để tìm hiểu giá trị cuối cùng vì mỗi lần các khối giao dịch, khối người quan sát sẽ cháy. Trong kịch bản ví dụ trên, nó sẽ cháy một lần cho 5 và một lần cho 6 bất kể ai upvoted đầu tiên. Bạn cần khối hoàn thành nếu bạn muốn tìm hiểu xem giao dịch cụ thể của bạn có thành công hay không và không chỉ là giá trị tại vị trí đó ngay bây giờ.

Và, chỉ để được hoàn chỉnh, có thêm một phương pháp gọi là runTransactionBlock:andCompletionBlock:withLocalEvents:. Nếu những người khác cũng đang viết thư cho cùng một vị trí, khối giao dịch có thể chạy nhiều lần. Điều này xảy ra nếu nó phát hiện ra rằng nó đang chạy trên dữ liệu cũ. Khi nó chạy thành công trên dữ liệu mới, nó sẽ gọi khối hoàn thành. Tuy nhiên, bạn sẽ thấy rằng mỗi khi nó chạy, nó sẽ kích hoạt bất kỳ khối quan sát nào tại vị trí đó. Nếu bạn không muốn điều này xảy ra, bạn phải vượt qua NO để withLocalEvents:. Firebase của bạn sẽ kích hoạt các sự kiện tại vị trí đó bất cứ khi nào một văn bản được xác nhận đi qua, nhưng các ghi tạm thời của giao dịch địa phương của bạn, chưa được xác nhận, sẽ không.

Nhìn lại ví dụ mà bạn và một người khác đang cố gắng để upvote cùng một lúc. Theo mặc định, người quan sát sẽ kích hoạt ngay khi bạn cố cập nhật số đếm từ 4 đến 5. Giao dịch thực tế có thể không thành công vì người khác đã đẩy số lượng upvote từ 4 lên 5 cùng một lúc. Khối giao dịch của bạn sau đó sẽ chạy lại với dữ liệu mới, 5 và thấy rằng nó sẽ đẩy số lượng lên 6. Với sự kiện cục bộ được đặt thành KHÔNG, người quan sát sẽ kích hoạt sau khi máy chủ cho phép bạn biết ai đó đã đẩy số lượng upvote từ 4 đến 5 và không phải khi bạn cố gắng cập nhật số đếm từ 4 đến 5.

Đây không phải là vấn đề lớn với những thứ đơn giản như upvotes mà mọi người chỉ tăng, nhưng nếu bạn có khả năng đẩy dữ liệu khác người dùng, bất kỳ người quan sát nào ở vị trí đều có thể thấy dữ liệu nhảy xung quanh trước khi cuối cùng giải quyết.

+4

Câu trả lời này sẽ được thêm vào tài liệu API Firebase ... không có tính năng đùa. – Reed

+1

Thành thật mà nói, nó giải thích nó một cách hoàn hảo. Chúc mừng anh em –

+0

@katfang nếu bạn có thể viết tương đương cho Swift, nó sẽ rất hữu ích. Cảm ơn nhiều – bibscy

Các vấn đề liên quan