iOS:fix when obj_retain DoricContext cause crash

This commit is contained in:
pengfeizhou 2021-02-09 15:09:52 +08:00 committed by osborn
parent a7e042174f
commit 3fa9124801
6 changed files with 23 additions and 19 deletions

View File

@ -111,8 +111,7 @@ - (void)onConnectExceptionEvent {
- (void)onStartDebugEvent:(NSNotification *)notification { - (void)onStartDebugEvent:(NSNotification *)notification {
NSString *contextId = notification.object; NSString *contextId = notification.object;
ShowToast(contextId, DoricGravityBottom); ShowToast(contextId, DoricGravityBottom);
for (NSValue *value in [[DoricContextManager instance] aliveContexts]) { for (DoricContext *context in [[DoricContextManager instance] aliveContexts]) {
DoricContext *context = value.nonretainedObjectValue;
BOOL result = [context.contextId compare:contextId] == NSOrderedSame; BOOL result = [context.contextId compare:contextId] == NSOrderedSame;
if (result) { if (result) {
_context = context; _context = context;

View File

@ -58,17 +58,18 @@ - (void)viewDidLoad {
[self.navigationController pushViewController:[QRScanViewController new] animated:NO]; [self.navigationController pushViewController:[QRScanViewController new] animated:NO];
} }
} }
- (void)onClose { - (void)onClose {
[[DoricDev instance] closeDevMode]; [[DoricDev instance] closeDevMode];
[self.navigationController popViewControllerAnimated:YES]; [self.navigationController popViewControllerAnimated:YES];
} }
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [DoricContextManager.instance aliveContexts].count; return [DoricContextManager.instance aliveContexts].count;
} }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSValue *value = [DoricContextManager.instance aliveContexts][(NSUInteger) indexPath.row]; DoricContext *context = [DoricContextManager.instance aliveContexts][(NSUInteger) indexPath.row];
DoricContext *context = value.nonretainedObjectValue;
NSString *path = context.source; NSString *path = context.source;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (cell == nil) { if (cell == nil) {
@ -84,8 +85,7 @@ - (BOOL)isSimulator {
} }
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSValue *value = [DoricContextManager.instance aliveContexts][(NSUInteger) indexPath.row]; DoricContext *context = [DoricContextManager.instance aliveContexts][(NSUInteger) indexPath.row];
DoricContext *context = value.nonretainedObjectValue;
[[NSNotificationCenter defaultCenter] postNotificationName:@"StartDebugEvent" object:context.contextId]; [[NSNotificationCenter defaultCenter] postNotificationName:@"StartDebugEvent" object:context.contextId];
NSDictionary *jsonDic = @{ NSDictionary *jsonDic = @{
@"cmd": @"DEBUG", @"cmd": @"DEBUG",

View File

@ -64,8 +64,7 @@ - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message {
} else if ([cmd compare:@"RELOAD"] == NSOrderedSame) { } else if ([cmd compare:@"RELOAD"] == NSOrderedSame) {
NSString *source = [[dic valueForKey:@"source"] mutableCopy]; NSString *source = [[dic valueForKey:@"source"] mutableCopy];
NSString *script = [dic valueForKey:@"script"]; NSString *script = [dic valueForKey:@"script"];
for (NSValue *value in [[DoricContextManager instance] aliveContexts]) { for (DoricContext *context in [[DoricContextManager instance] aliveContexts]) {
DoricContext *context = value.nonretainedObjectValue;
if ([source containsString:context.source] || [context.source isEqualToString:@"__dev__"]) { if ([source containsString:context.source] || [context.source isEqualToString:@"__dev__"]) {
[context reload:script]; [context reload:script];
} }

View File

@ -34,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN
- (DoricContext *)getContext:(NSString *)contextId; - (DoricContext *)getContext:(NSString *)contextId;
- (NSArray *)aliveContexts; - (NSArray <DoricContext *> *)aliveContexts;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@ -25,7 +25,7 @@
@interface DoricContextManager () @interface DoricContextManager ()
@property(nonatomic) NSInteger counter; @property(nonatomic) NSInteger counter;
@property(nonatomic, strong) NSMutableDictionary <NSString *, NSValue *> *doricContextMap; @property(nonatomic, strong) NSMapTable <NSString *, DoricContext *> *contextMapTable;
@property(nonatomic, strong) dispatch_queue_t mapQueue; @property(nonatomic, strong) dispatch_queue_t mapQueue;
@end @end
@ -33,9 +33,11 @@ @implementation DoricContextManager
- (instancetype)init { - (instancetype)init {
if (self = [super init]) { if (self = [super init]) {
_doricContextMap = [[NSMutableDictionary alloc] init];
_counter = 0; _counter = 0;
_mapQueue = dispatch_queue_create("doric.contextmap", DISPATCH_QUEUE_SERIAL); _mapQueue = dispatch_queue_create("doric.contextmap", DISPATCH_QUEUE_SERIAL);
_contextMapTable = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsCopyIn
valueOptions:NSPointerFunctionsWeakMemory
capacity:0];
} }
return self; return self;
} }
@ -52,8 +54,7 @@ + (instancetype)instance {
- (void)createContext:(DoricContext *)context script:(NSString *)script source:(NSString *)source { - (void)createContext:(DoricContext *)context script:(NSString *)script source:(NSString *)source {
context.contextId = [NSString stringWithFormat:@"%ld", (long) ++self.counter]; context.contextId = [NSString stringWithFormat:@"%ld", (long) ++self.counter];
dispatch_sync(self.mapQueue, ^() { dispatch_sync(self.mapQueue, ^() {
NSValue *value = [NSValue valueWithNonretainedObject:context]; [self.contextMapTable setObject:context forKey:context.contextId];
self.doricContextMap[context.contextId] = value;
}); });
[context.driver createContext:context.contextId script:script source:source]; [context.driver createContext:context.contextId script:script source:source];
} }
@ -61,8 +62,7 @@ - (void)createContext:(DoricContext *)context script:(NSString *)script source:(
- (DoricContext *)getContext:(NSString *)contextId { - (DoricContext *)getContext:(NSString *)contextId {
__block DoricContext *context; __block DoricContext *context;
dispatch_sync(self.mapQueue, ^{ dispatch_sync(self.mapQueue, ^{
NSValue *value = self.doricContextMap[contextId]; context = [self.contextMapTable objectForKey:contextId];
context = value.nonretainedObjectValue;
}); });
return context; return context;
} }
@ -70,12 +70,18 @@ - (DoricContext *)getContext:(NSString *)contextId {
- (void)destroyContext:(DoricContext *)context { - (void)destroyContext:(DoricContext *)context {
NSString *contextId = context.contextId; NSString *contextId = context.contextId;
dispatch_sync(self.mapQueue, ^() { dispatch_sync(self.mapQueue, ^() {
[self.doricContextMap removeObjectForKey:contextId]; [self.contextMapTable removeObjectForKey:contextId];
}); });
} }
- (NSArray *)aliveContexts { - (NSArray <DoricContext *> *)aliveContexts {
return [self.doricContextMap allValues]; NSEnumerator *enumerator = [self.contextMapTable objectEnumerator];
NSMutableArray *ret = [NSMutableArray new];
DoricContext *context;
while ((context = [enumerator nextObject])) {
[ret addObject:context];
}
return ret;
} }
@end @end

View File

@ -34,7 +34,7 @@ @implementation DoricBridgeExtension
- (id)callNativeWithContextId:(NSString *)contextId module:(NSString *)module method:(NSString *)method callbackId:(NSString *)callbackId argument:(id)argument { - (id)callNativeWithContextId:(NSString *)contextId module:(NSString *)module method:(NSString *)method callbackId:(NSString *)callbackId argument:(id)argument {
__strong DoricContext *context = [[DoricContextManager instance] getContext:contextId]; __strong DoricContext *context = [[DoricContextManager instance] getContext:contextId];
if (context.destroyed) { if (!context || context.destroyed) {
return nil; return nil;
} }
Class pluginClass = [self.registry acquireNativePlugin:module]; Class pluginClass = [self.registry acquireNativePlugin:module];