From 7a1d96e8aae45964cfbe8a1eb5237ba276aeb906 Mon Sep 17 00:00:00 2001 From: Peter Argany Date: Fri, 8 Nov 2019 15:30:05 -0800 Subject: [PATCH] Remove main thread constraint from RCTReloadCommand Summary: In D17880909 I migrated `[bridge reload]` to RCTReloadCommand. One thing I didn't consider too much is the plethora of things which trigger a reload, and the `RCTAssertMainQueue()` constraint. I'd rather use locking (to protect listeners list) than requiring reloads be called from main thread. Changelog: [iOS][Fixed] Fix potential assert firing in RCTReloadCommand Reviewed By: rodrigos-facebook Differential Revision: D18353156 fbshipit-source-id: d20b851fc5fe6c3518dfa3db8f1fc075cf7edee9 --- React/Base/RCTReloadCommand.m | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/React/Base/RCTReloadCommand.m b/React/Base/RCTReloadCommand.m index 774ff5d0f19..c4b83bc136e 100644 --- a/React/Base/RCTReloadCommand.m +++ b/React/Base/RCTReloadCommand.m @@ -11,40 +11,46 @@ #import "RCTKeyCommands.h" #import "RCTUtils.h" -/** main queue only */ static NSHashTable> *listeners; +static NSLock *listenersLock; NSString *const RCTTriggerReloadCommandNotification = @"RCTTriggerReloadCommandNotification"; NSString *const RCTTriggerReloadCommandReasonKey = @"reason"; void RCTRegisterReloadCommandListener(id listener) { + if (!listenersLock) { + listenersLock = [NSLock new]; + } + [listenersLock lock]; + if (!listeners) { + listeners = [NSHashTable weakObjectsHashTable]; + } +#if RCT_DEV RCTAssertMainQueue(); // because registerKeyCommandWithInput: must be called on the main thread static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - listeners = [NSHashTable weakObjectsHashTable]; [[RCTKeyCommands sharedInstance] registerKeyCommandWithInput:@"r" modifierFlags:UIKeyModifierCommand action: ^(__unused UIKeyCommand *command) { - RCTTriggerReloadCommandListeners(@"Command + R"); - }]; + RCTTriggerReloadCommandListeners(@"Command + R"); + }]; }); +#endif [listeners addObject:listener]; + [listenersLock unlock]; } void RCTTriggerReloadCommandListeners(NSString *reason) { - RCTAssertMainQueue(); - + [listenersLock lock]; [[NSNotificationCenter defaultCenter] postNotificationName:RCTTriggerReloadCommandNotification object:nil userInfo:@{RCTTriggerReloadCommandReasonKey: RCTNullIfNil(reason)} ]; - // Copy to protect against mutation-during-enumeration. - // If listeners hasn't been initialized yet we get nil, which works just fine. - NSArray> *copiedListeners = [listeners allObjects]; - for (id l in copiedListeners) { + for (id l in [listeners allObjects]) { [l didReceiveReloadCommand]; } + [listenersLock unlock]; }