diff --git a/ios/RNFirebase/database/RNFirebaseDatabase.m b/ios/RNFirebase/database/RNFirebaseDatabase.m index 69a235fb..9d6b2730 100644 --- a/ios/RNFirebase/database/RNFirebaseDatabase.m +++ b/ios/RNFirebase/database/RNFirebaseDatabase.m @@ -22,44 +22,44 @@ RCT_EXPORT_MODULE(); return self; } -RCT_EXPORT_METHOD(goOnline:(NSString *) appDisplayName) { +RCT_EXPORT_METHOD(goOnline:(NSString *)appDisplayName) { [[RNFirebaseDatabase getDatabaseForApp:appDisplayName] goOnline]; } -RCT_EXPORT_METHOD(goOffline:(NSString *) appDisplayName) { +RCT_EXPORT_METHOD(goOffline:(NSString *)appDisplayName) { [[RNFirebaseDatabase getDatabaseForApp:appDisplayName] goOffline]; } -RCT_EXPORT_METHOD(setPersistence:(NSString *) appDisplayName - state:(BOOL) state) { +RCT_EXPORT_METHOD(setPersistence:(NSString *)appDisplayName + state:(BOOL)state) { [RNFirebaseDatabase getDatabaseForApp:appDisplayName].persistenceEnabled = state; } -RCT_EXPORT_METHOD(setPersistenceCacheSizeBytes:(NSString *) appDisplayName - size:(NSInteger *) size) { +RCT_EXPORT_METHOD(setPersistenceCacheSizeBytes:(NSString *)appDisplayName + size:(NSInteger *)size) { [RNFirebaseDatabase getDatabaseForApp:appDisplayName].persistenceCacheSizeBytes = (NSUInteger)size; } -RCT_EXPORT_METHOD(enableLogging:(BOOL) enabled) { +RCT_EXPORT_METHOD(enableLogging:(BOOL)enabled) { [FIRDatabase setLoggingEnabled:enabled]; } -RCT_EXPORT_METHOD(keepSynced:(NSString *) appDisplayName - key:(NSString *) key - path:(NSString *) path - modifiers:(NSArray *) modifiers - state:(BOOL) state) { +RCT_EXPORT_METHOD(keepSynced:(NSString *)appDisplayName + key:(NSString *)key + path:(NSString *)path + modifiers:(NSArray *)modifiers + state:(BOOL)state) { FIRDatabaseQuery *query = [self getInternalReferenceForApp:appDisplayName key:key path:path modifiers:modifiers].query; [query keepSynced:state]; } -RCT_EXPORT_METHOD(transactionTryCommit:(NSString *) appDisplayName - transactionId:(nonnull NSNumber *) transactionId - updates:(NSDictionary *) updates) { +RCT_EXPORT_METHOD(transactionTryCommit:(NSString *)appDisplayName + transactionId:(nonnull NSNumber *)transactionId + updates:(NSDictionary *)updates) { __block NSMutableDictionary *transactionState; dispatch_sync(_transactionQueue, ^{ - transactionState = _transactions[transactionId]; + transactionState = _transactions[[transactionId stringValue]]; }); if (!transactionState) { @@ -82,171 +82,166 @@ RCT_EXPORT_METHOD(transactionTryCommit:(NSString *) appDisplayName } -RCT_EXPORT_METHOD(transactionStart:(NSString *) appDisplayName - path:(NSString *) path - transactionId:(nonnull NSNumber *) transactionId - applyLocally:(BOOL) applyLocally) { +RCT_EXPORT_METHOD(transactionStart:(NSString *)appDisplayName + path:(NSString *)path + transactionId:(nonnull NSNumber *)transactionId + applyLocally:(BOOL)applyLocally) { dispatch_async(_transactionQueue, ^{ NSMutableDictionary *transactionState = [NSMutableDictionary new]; dispatch_semaphore_t sema = dispatch_semaphore_create(0); transactionState[@"semaphore"] = sema; FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; - [ref runTransactionBlock:^FIRTransactionResult * _Nonnull(FIRMutableData * - _Nonnull currentData) { - dispatch_barrier_async(_transactionQueue, ^{ - [_transactions setValue:transactionState forKey:transactionId]; - NSDictionary *updateMap = [self createTransactionUpdateMap:appDisplayName transactionId:transactionId updatesData:currentData]; - [RNFirebaseUtil sendJSEvent:self name:DATABASE_TRANSACTION_EVENT body:updateMap]; - }); + [ref runTransactionBlock:^FIRTransactionResult *_Nonnull (FIRMutableData *_Nonnull currentData) { + dispatch_barrier_async(_transactionQueue, ^{ + [_transactions setValue:transactionState forKey:[transactionId stringValue]]; + NSDictionary *updateMap = [self createTransactionUpdateMap:appDisplayName transactionId:transactionId updatesData:currentData]; + [RNFirebaseUtil sendJSEvent:self name:DATABASE_TRANSACTION_EVENT body:updateMap]; + }); - // wait for the js event handler to call tryCommitTransaction - // this wait occurs on the Firebase Worker Queue - // so if the tryCommitTransaction fails to signal the semaphore - // no further blocks will be executed by Firebase until the timeout expires - dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC); - BOOL timedout = dispatch_semaphore_wait(sema, delayTime) != 0; + // wait for the js event handler to call tryCommitTransaction + // this wait occurs on the Firebase Worker Queue + // so if the tryCommitTransaction fails to signal the semaphore + // no further blocks will be executed by Firebase until the timeout expires + dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC); + BOOL timedout = dispatch_semaphore_wait(sema, delayTime) != 0; - BOOL abort = [transactionState valueForKey:@"abort"] || timedout; - id value = [transactionState valueForKey:@"value"]; + BOOL abort = [transactionState valueForKey:@"abort"] || timedout; + id value = [transactionState valueForKey:@"value"]; - dispatch_barrier_async(_transactionQueue, ^{ - [_transactions removeObjectForKey:transactionId]; - }); + dispatch_barrier_async(_transactionQueue, ^{ + [_transactions removeObjectForKey:[transactionId stringValue]]; + }); - if (abort) { - return [FIRTransactionResult abort]; - } else { - currentData.value = value; - return [FIRTransactionResult successWithValue:currentData]; - } - } - andCompletionBlock: - ^(NSError *_Nullable databaseError, BOOL committed, FIRDataSnapshot *_Nullable snapshot) { + if (abort) { + return [FIRTransactionResult abort]; + } else { + currentData.value = value; + return [FIRTransactionResult successWithValue:currentData]; + } + } andCompletionBlock:^(NSError *_Nullable databaseError, BOOL committed, FIRDataSnapshot *_Nullable snapshot) { NSDictionary *resultMap = [self createTransactionResultMap:appDisplayName transactionId:transactionId error:databaseError committed:committed snapshot:snapshot]; [RNFirebaseUtil sendJSEvent:self name:DATABASE_TRANSACTION_EVENT body:resultMap]; - } - withLocalEvents: - applyLocally]; + } withLocalEvents:applyLocally]; }); } -RCT_EXPORT_METHOD(onDisconnectSet:(NSString *) appDisplayName - path:(NSString *) path - props:(NSDictionary *) props - resolver:(RCTPromiseResolveBlock) resolve - rejecter:(RCTPromiseRejectBlock) reject) { +RCT_EXPORT_METHOD(onDisconnectSet:(NSString *)appDisplayName + path:(NSString *)path + props:(NSDictionary *)props + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref onDisconnectSetValue:props[@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(onDisconnectUpdate:(NSString *) appDisplayName - path:(NSString *) path - props:(NSDictionary *) props - resolver:(RCTPromiseResolveBlock) resolve - rejecter:(RCTPromiseRejectBlock) reject) { +RCT_EXPORT_METHOD(onDisconnectUpdate:(NSString *)appDisplayName + path:(NSString *)path + props:(NSDictionary *)props + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref onDisconnectUpdateChildValues:props withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(onDisconnectRemove:(NSString *) appDisplayName - path:(NSString *) path - resolver:(RCTPromiseResolveBlock) resolve - rejecter:(RCTPromiseRejectBlock) reject) { +RCT_EXPORT_METHOD(onDisconnectRemove:(NSString *)appDisplayName + path:(NSString *)path + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref onDisconnectRemoveValueWithCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(onDisconnectCancel:(NSString *) appDisplayName - path:(NSString *) path - resolver:(RCTPromiseResolveBlock) resolve - rejecter:(RCTPromiseRejectBlock) reject) { +RCT_EXPORT_METHOD(onDisconnectCancel:(NSString *)appDisplayName + path:(NSString *)path + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref cancelDisconnectOperationsWithCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(set:(NSString *) appDisplayName - path:(NSString *) path - props:(NSDictionary *) props - resolver:(RCTPromiseResolveBlock) resolve - rejecter:(RCTPromiseRejectBlock) reject) { +RCT_EXPORT_METHOD(set:(NSString *)appDisplayName + path:(NSString *)path + props:(NSDictionary *)props + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref setValue:[props valueForKey:@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(setPriority:(NSString *) appDisplayName - path:(NSString *) path - priority:(NSDictionary *) priority - resolver:(RCTPromiseResolveBlock) resolve - rejecter:(RCTPromiseRejectBlock) reject) { +RCT_EXPORT_METHOD(setPriority:(NSString *)appDisplayName + path:(NSString *)path + priority:(NSDictionary *)priority + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref setPriority:[priority valueForKey:@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(setWithPriority:(NSString *) appDisplayName - path:(NSString *) path - data:(NSDictionary *) data - priority:(NSDictionary *) priority - resolver:(RCTPromiseResolveBlock) resolve - rejecter:(RCTPromiseRejectBlock) reject) { +RCT_EXPORT_METHOD(setWithPriority:(NSString *)appDisplayName + path:(NSString *)path + data:(NSDictionary *)data + priority:(NSDictionary *)priority + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref setValue:[data valueForKey:@"value"] andPriority:[priority valueForKey:@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(update:(NSString *) appDisplayName - path:(NSString *) path - props:(NSDictionary *) props - resolver:(RCTPromiseResolveBlock) resolve - rejecter:(RCTPromiseRejectBlock) reject) { +RCT_EXPORT_METHOD(update:(NSString *)appDisplayName + path:(NSString *)path + props:(NSDictionary *)props + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref updateChildValues:props withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(remove:(NSString *) appDisplayName - path:(NSString *) path - resolver:(RCTPromiseResolveBlock) resolve - rejecter:(RCTPromiseRejectBlock) reject) { +RCT_EXPORT_METHOD(remove:(NSString *)appDisplayName + path:(NSString *)path + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref removeValueWithCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(once:(NSString *) appDisplayName - key:(NSString *) key - path:(NSString *) path - modifiers:(NSArray *) modifiers - eventName:(NSString *) eventName - resolver:(RCTPromiseResolveBlock) resolve - rejecter:(RCTPromiseRejectBlock) reject) { +RCT_EXPORT_METHOD(once:(NSString *)appDisplayName + key:(NSString *)key + path:(NSString *)path + modifiers:(NSArray *)modifiers + eventName:(NSString *)eventName + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { RNFirebaseDatabaseReference *ref = [self getInternalReferenceForApp:appDisplayName key:key path:path modifiers:modifiers]; [ref once:eventName resolver:resolve rejecter:reject]; } -RCT_EXPORT_METHOD(on:(NSString *) appDisplayName - props:(NSDictionary *) props) { +RCT_EXPORT_METHOD(on:(NSString *)appDisplayName + props:(NSDictionary *)props) { RNFirebaseDatabaseReference *ref = [self getCachedInternalReferenceForApp:appDisplayName props:props]; [ref on:props[@"eventType"] registration:props[@"registration"]]; } -RCT_EXPORT_METHOD(off:(NSString *) key - eventRegistrationKey:(NSString *) eventRegistrationKey) { +RCT_EXPORT_METHOD(off:(NSString *)key + eventRegistrationKey:(NSString *)eventRegistrationKey) { RNFirebaseDatabaseReference *ref = _dbReferences[key]; if (ref) { [ref removeEventListener:eventRegistrationKey]; @@ -331,7 +326,7 @@ RCT_EXPORT_METHOD(off:(NSString *) key message = [RNFirebaseDatabase getMessageWithService:@"The write was canceled by the user." service:service fullCode:code]; break; - // TODO: Missing iOS equivalent codes + // TODO: Missing iOS equivalent codes case -1: code = [RNFirebaseDatabase getCodeWithService:service code:@"data-stale"]; message = [RNFirebaseDatabase getMessageWithService:@"The transaction needs to be run again with current data." service:service fullCode:code]; @@ -413,8 +408,7 @@ RCT_EXPORT_METHOD(off:(NSString *) key return @[DATABASE_SYNC_EVENT, DATABASE_TRANSACTION_EVENT]; } -+ (BOOL)requiresMainQueueSetup -{ ++ (BOOL)requiresMainQueueSetup { return YES; } @@ -424,3 +418,7 @@ RCT_EXPORT_METHOD(off:(NSString *) key @implementation RNFirebaseDatabase @end #endif + + + + diff --git a/ios/RNFirebase/database/RNFirebaseDatabaseReference.m b/ios/RNFirebase/database/RNFirebaseDatabaseReference.m index a6caf8c2..5a4a8a4b 100644 --- a/ios/RNFirebase/database/RNFirebaseDatabaseReference.m +++ b/ios/RNFirebase/database/RNFirebaseDatabaseReference.m @@ -5,10 +5,10 @@ #if __has_include() - (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter - appDisplayName:(NSString *) appDisplayName - key:(NSString *) key - refPath:(NSString *) refPath - modifiers:(NSArray *) modifiers { + appDisplayName:(NSString *)appDisplayName + key:(NSString *)key + refPath:(NSString *)refPath + modifiers:(NSArray *)modifiers { self = [super init]; if (self) { _emitter = emitter; @@ -22,14 +22,14 @@ } - (void)removeEventListener:(NSString *)eventRegistrationKey { - FIRDatabaseHandle handle = (FIRDatabaseHandle) [_listeners[eventRegistrationKey] integerValue]; + FIRDatabaseHandle handle = (FIRDatabaseHandle)[_listeners[eventRegistrationKey] integerValue]; if (handle) { [_query removeObserverWithHandle:handle]; [_listeners removeObjectForKey:eventRegistrationKey]; } } -- (void)on:(NSString *) eventType registration:(NSDictionary *) registration { +- (void)on:(NSString *)eventType registration:(NSDictionary *)registration { NSString *eventRegistrationKey = registration[@"eventRegistrationKey"]; if (![self hasEventListener:eventRegistrationKey]) { id andPreviousSiblingKeyWithBlock = ^(FIRDataSnapshot *_Nonnull snapshot, NSString *_Nullable previousChildName) { @@ -46,9 +46,9 @@ } } -- (void)once:(NSString *) eventType - resolver:(RCTPromiseResolveBlock) resolve - rejecter:(RCTPromiseRejectBlock) reject { +- (void)once:(NSString *)eventType + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject { FIRDataEventType firDataEventType = (FIRDataEventType)[self eventTypeFromName:eventType]; [_query observeSingleEventOfType:firDataEventType andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *_Nonnull snapshot, NSString *_Nullable previousChildName) { NSDictionary *data = [RNFirebaseDatabaseReference snapshotToDictionary:snapshot previousChildName:previousChildName]; @@ -59,33 +59,33 @@ }]; } -- (void)handleDatabaseEvent:(NSString *) eventType - registration:(NSDictionary *) registration - dataSnapshot:(FIRDataSnapshot *) dataSnapshot - previousChildName:(NSString *) previousChildName { +- (void)handleDatabaseEvent:(NSString *)eventType + registration:(NSDictionary *)registration + dataSnapshot:(FIRDataSnapshot *)dataSnapshot + previousChildName:(NSString *)previousChildName { NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; NSDictionary *data = [RNFirebaseDatabaseReference snapshotToDictionary:dataSnapshot previousChildName:previousChildName]; - + [event setValue:data forKey:@"data"]; [event setValue:_key forKey:@"key"]; [event setValue:eventType forKey:@"eventType"]; [event setValue:registration forKey:@"registration"]; - + [RNFirebaseUtil sendJSEvent:self.emitter name:DATABASE_SYNC_EVENT body:event]; } -- (void)handleDatabaseError:(NSDictionary *) registration +- (void)handleDatabaseError:(NSDictionary *)registration error:(NSError *)error { NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; [event setValue:_key forKey:@"key"]; [event setValue:[RNFirebaseDatabase getJSError:error] forKey:@"error"]; [event setValue:registration forKey:@"registration"]; - + [RNFirebaseUtil sendJSEvent:self.emitter name:DATABASE_SYNC_EVENT body:event]; } -+ (NSDictionary *)snapshotToDictionary:(FIRDataSnapshot *) dataSnapshot - previousChildName:(NSString *) previousChildName { ++ (NSDictionary *)snapshotToDictionary:(FIRDataSnapshot *)dataSnapshot + previousChildName:(NSString *)previousChildName { NSMutableDictionary *result = [[NSMutableDictionary alloc] init]; NSDictionary *snapshot = [RNFirebaseDatabaseReference snapshotToDict:dataSnapshot]; @@ -97,7 +97,7 @@ + (NSDictionary *)snapshotToDict:(FIRDataSnapshot *)dataSnapshot { NSMutableDictionary *snapshot = [[NSMutableDictionary alloc] init]; - + [snapshot setValue:dataSnapshot.key forKey:@"key"]; [snapshot setValue:@(dataSnapshot.exists) forKey:@"exists"]; [snapshot setValue:@(dataSnapshot.hasChildren) forKey:@"hasChildren"]; @@ -105,11 +105,11 @@ [snapshot setValue:[RNFirebaseDatabaseReference getChildKeys:dataSnapshot] forKey:@"childKeys"]; [snapshot setValue:dataSnapshot.priority forKey:@"priority"]; [snapshot setValue:dataSnapshot.value forKey:@"value"]; - + return snapshot; } -+ (NSMutableArray *) getChildKeys:(FIRDataSnapshot *) snapshot { ++ (NSMutableArray *)getChildKeys:(FIRDataSnapshot *)snapshot { NSMutableArray *childKeys = [NSMutableArray array]; if (snapshot.childrenCount > 0) { NSEnumerator *children = [snapshot children]; @@ -121,7 +121,7 @@ return childKeys; } -- (FIRDatabaseQuery *)buildQueryAtPathWithModifiers:(NSString *) path +- (FIRDatabaseQuery *)buildQueryAtPathWithModifiers:(NSString *)path modifiers:(NSArray *)modifiers { FIRDatabase *firebaseDatabase = [RNFirebaseDatabase getDatabaseForApp:_appDisplayName]; FIRDatabaseQuery *query = [[firebaseDatabase reference] child:path]; @@ -186,7 +186,7 @@ } } -- (BOOL)hasEventListener:(NSString *) eventRegistrationKey { +- (BOOL)hasEventListener:(NSString *)eventRegistrationKey { return _listeners[eventRegistrationKey] != nil; } @@ -214,3 +214,4 @@ #endif @end +