iOS: Ensure that rendering operations are serialized to prevent timing errors
This commit is contained in:
		@@ -109,7 +109,14 @@ - (id)findClass:(Class)clz target:(id)target context:(DoricContext *)context met
 | 
			
		||||
                    const char *retType = methodSignature.methodReturnType;
 | 
			
		||||
                    if (!strcmp(retType, @encode(void))) {
 | 
			
		||||
                        ret = nil;
 | 
			
		||||
                        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
 | 
			
		||||
                        DoricThreadMode mode = [target threadMode:methodName];
 | 
			
		||||
                        if (mode == DoricThreadModeUI) {
 | 
			
		||||
                            dispatch_async(dispatch_get_main_queue(), block);
 | 
			
		||||
                        } else if (mode == DoricThreadModeJS) {
 | 
			
		||||
                            block();
 | 
			
		||||
                        } else {
 | 
			
		||||
                            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
 | 
			
		||||
                        }
 | 
			
		||||
                    } else if (!strcmp(retType, @encode(id))) {
 | 
			
		||||
                        void *retValue;
 | 
			
		||||
                        block();
 | 
			
		||||
 
 | 
			
		||||
@@ -25,10 +25,21 @@
 | 
			
		||||
#import "DoricPromise.h"
 | 
			
		||||
#import "DoricRegistry.h"
 | 
			
		||||
 | 
			
		||||
typedef NS_ENUM(NSUInteger, DoricThreadMode) {
 | 
			
		||||
    DoricThreadModeUI = 1,
 | 
			
		||||
    DoricThreadModeJS = 2,
 | 
			
		||||
    DoricThreadModeIndependent = 3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
NS_ASSUME_NONNULL_BEGIN
 | 
			
		||||
 | 
			
		||||
@interface DoricNativePlugin : DoricContextHolder
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Determines which thread this method should run on
 | 
			
		||||
 * @param method name of method
 | 
			
		||||
 * @return thread where this method should run on,default is DoricThreadModeIndependent
 | 
			
		||||
 * */
 | 
			
		||||
- (DoricThreadMode)threadMode:(NSString *)method;
 | 
			
		||||
@end
 | 
			
		||||
 | 
			
		||||
NS_ASSUME_NONNULL_END
 | 
			
		||||
 
 | 
			
		||||
@@ -23,5 +23,7 @@
 | 
			
		||||
#import "DoricNativePlugin.h"
 | 
			
		||||
 | 
			
		||||
@implementation DoricNativePlugin
 | 
			
		||||
 | 
			
		||||
- (DoricThreadMode)threadMode:(NSString *)method {
 | 
			
		||||
    return DoricThreadModeIndependent;
 | 
			
		||||
}
 | 
			
		||||
@end
 | 
			
		||||
 
 | 
			
		||||
@@ -29,60 +29,56 @@
 | 
			
		||||
 | 
			
		||||
@implementation DoricShaderPlugin
 | 
			
		||||
 | 
			
		||||
- (DoricThreadMode)threadMode:(NSString *)method {
 | 
			
		||||
    return DoricThreadModeUI;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)render:(NSDictionary *)argument withPromise:(DoricPromise *)promise {
 | 
			
		||||
    if (!argument) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    [self.doricContext.performanceProfile prepare:@"Render"];
 | 
			
		||||
    __weak typeof(self) _self = self;
 | 
			
		||||
    [self.doricContext dispatchToMainQueue:^{
 | 
			
		||||
        __strong typeof(_self) self = _self;
 | 
			
		||||
        if (self.doricContext == nil) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        [self.doricContext.performanceProfile start:@"Render"];
 | 
			
		||||
        NSString *viewId = [argument optString:@"id"];
 | 
			
		||||
    if (self.doricContext == nil) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    [self.doricContext.performanceProfile start:@"Render"];
 | 
			
		||||
    NSString *viewId = [argument optString:@"id"];
 | 
			
		||||
 | 
			
		||||
        if (self.doricContext.rootNode.viewId == nil && [@"Root" isEqualToString:[argument optString:@"type"]]) {
 | 
			
		||||
            self.doricContext.rootNode.viewId = viewId;
 | 
			
		||||
            [self.doricContext.rootNode blend:[argument optObject:@"props"]];
 | 
			
		||||
            [self.doricContext.rootNode requestLayout];
 | 
			
		||||
        } else {
 | 
			
		||||
            DoricViewNode *viewNode = [self.doricContext targetViewNode:viewId];
 | 
			
		||||
            [viewNode blend:[argument optObject:@"props"]];
 | 
			
		||||
            [viewNode requestLayout];
 | 
			
		||||
        }
 | 
			
		||||
        [promise resolve:nil];
 | 
			
		||||
        [self.doricContext.performanceProfile end:@"Render"];
 | 
			
		||||
    }];
 | 
			
		||||
    if (self.doricContext.rootNode.viewId == nil && [@"Root" isEqualToString:[argument optString:@"type"]]) {
 | 
			
		||||
        self.doricContext.rootNode.viewId = viewId;
 | 
			
		||||
        [self.doricContext.rootNode blend:[argument optObject:@"props"]];
 | 
			
		||||
        [self.doricContext.rootNode requestLayout];
 | 
			
		||||
    } else {
 | 
			
		||||
        DoricViewNode *viewNode = [self.doricContext targetViewNode:viewId];
 | 
			
		||||
        [viewNode blend:[argument optObject:@"props"]];
 | 
			
		||||
        [viewNode requestLayout];
 | 
			
		||||
    }
 | 
			
		||||
    [promise resolve:nil];
 | 
			
		||||
    [self.doricContext.performanceProfile end:@"Render"];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)command:(NSDictionary *)argument withPromise:(DoricPromise *)promise {
 | 
			
		||||
    __weak typeof(self) _self = self;
 | 
			
		||||
    [self.doricContext dispatchToMainQueue:^{
 | 
			
		||||
        __strong typeof(_self) self = _self;
 | 
			
		||||
        if (self.doricContext == nil) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        NSArray *viewIds = [argument optArray:@"viewIds"];
 | 
			
		||||
        id args = argument[@"args"];
 | 
			
		||||
        NSString *name = [argument optString:@"name"];
 | 
			
		||||
        DoricViewNode *viewNode = nil;
 | 
			
		||||
        for (NSString *viewId in viewIds) {
 | 
			
		||||
            if (!viewNode) {
 | 
			
		||||
                viewNode = [self.doricContext targetViewNode:viewId];
 | 
			
		||||
            } else {
 | 
			
		||||
                if ([viewNode isKindOfClass:[DoricSuperNode class]]) {
 | 
			
		||||
                    viewNode = [((DoricSuperNode *) viewNode) subNodeWithViewId:viewId];
 | 
			
		||||
                }
 | 
			
		||||
    if (self.doricContext == nil) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    NSArray *viewIds = [argument optArray:@"viewIds"];
 | 
			
		||||
    id args = argument[@"args"];
 | 
			
		||||
    NSString *name = [argument optString:@"name"];
 | 
			
		||||
    DoricViewNode *viewNode = nil;
 | 
			
		||||
    for (NSString *viewId in viewIds) {
 | 
			
		||||
        if (!viewNode) {
 | 
			
		||||
            viewNode = [self.doricContext targetViewNode:viewId];
 | 
			
		||||
        } else {
 | 
			
		||||
            if ([viewNode isKindOfClass:[DoricSuperNode class]]) {
 | 
			
		||||
                viewNode = [((DoricSuperNode *) viewNode) subNodeWithViewId:viewId];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (!viewNode) {
 | 
			
		||||
            [promise reject:@"Cannot find opposite view"];
 | 
			
		||||
        } else {
 | 
			
		||||
            [self findClass:[viewNode class] target:viewNode method:name promise:promise argument:args];
 | 
			
		||||
        }
 | 
			
		||||
    }];
 | 
			
		||||
    }
 | 
			
		||||
    if (!viewNode) {
 | 
			
		||||
        [promise reject:@"Cannot find opposite view"];
 | 
			
		||||
    } else {
 | 
			
		||||
        [self findClass:[viewNode class] target:viewNode method:name promise:promise argument:args];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (id)createParamWithMethodName:(NSString *)method promise:(DoricPromise *)promise argument:(id)argument {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user