CDVYHInterface.m 5.74 KB
#import "CDVYHInterface.h"
#import "NSDictionary+Extensions.h"
#import "CDVYHInterfaceDelegate.h"
#import "YHNative.h"
#import <objc/runtime.h>

@interface CDVYHInterface ()
@property (strong, nonatomic) NSMutableDictionary *abilities;
@end

@implementation CDVYHInterface

- (NSMutableDictionary *)abilities
{
    _abilities = _abilities?:[[NSMutableDictionary alloc] initWithCapacity:1];
    return _abilities;
}

- (void)dealloc
{
    
}

- (void)eventTriggered:(CDVInvokedUrlCommand *)command
{
    __weak typeof(self)weakSelf = self;
    
    id <CDVYHInterfaceDelegate> yhif = nil;
    if ([self.viewController conformsToProtocol:@protocol(CDVYHInterfaceDelegate)]) {
        yhif = (id <CDVYHInterfaceDelegate>)self.viewController;
    }

    __weak typeof(yhif) weakIf = yhif;
    
    [self.commandDelegate runInBackground:^{
    
        NSDictionary *info = [command argumentAtIndex:0 withDefault:nil];
        if (!info) {
            return;
        }

        if (info.allKeys.count < 1) {
            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Unknown Event"];
            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
        }
        
        NSDictionary *options = nil;
        Class abilityClass = nil;
        SEL action = nil;
        NSString *ability = nil;
        
        for (NSString *key in info.allKeys) {
            if ([key isEqualToString:@"options"]) {
                options = info[key];
            } else {
                if (!abilityClass) {
                    ability = key;
                    abilityClass = [YHNative resolveActionName:key];
                    if (abilityClass && [NSStringFromClass(abilityClass) isEqualToString:@"YHNative_Message"]) {
                        // give a selector name, whatever...
                        action = NSSelectorFromString(@"yh_message");
                        break;
                    }
                }
            }
        }
        
        if (!abilityClass || !action) {
            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Unknown Event"];
            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
        }
        
        YHNative *native = weakSelf.abilities[NSStringFromClass(abilityClass)];
        if (!native) {
            native = [[abilityClass alloc] init];
            weakSelf.abilities[NSStringFromClass(abilityClass)] = native;
        }
        
        native.originalParams = info;

        BOOL canProcess = YES;
        if (weakIf && [weakIf respondsToSelector:@selector(nativeActionShouldBegin:)]) {
            canProcess = [weakIf nativeActionShouldBegin:native];
        }
        
        if (!canProcess) {
            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_NO_RESULT messageAsString:@"Not permitted"];
            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
            return;
        }
        
        __weak typeof(native) wn = native;
        
        [native workWithMethod:action options:options success:^(NSDictionary *info, BOOL keepCallback, NSDictionary *nativeInfo) {
            NSDictionary *retDict = nil;
            if (info) {
                retDict = @{ @"ability": ability, @"action": NSStringFromSelector(action), @"result": info };
            } else {
                retDict = @{ @"ability": ability, @"action": NSStringFromSelector(action), @"result": @{} };
            }
            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:retDict];
            pluginResult.keepCallback = @(keepCallback);
            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
            
            if (weakIf && [weakIf respondsToSelector:@selector(nativeAction:didEndWithResult:userInfo:)]) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [weakIf nativeAction:wn didEndWithResult:YES userInfo:nativeInfo];
                });
            }
            
        } failure:^(NSString *message) {
            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:message];
            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
            
            if (weakIf && [weakIf respondsToSelector:@selector(nativeAction:didEndWithResult:userInfo:)]) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [weakIf nativeAction:wn didEndWithResult:NO userInfo:nil];
                });
            }
        }];
    }];
}

- (BOOL)shouldOverrideLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSString *urlString = request.URL.absoluteString;
    switch (navigationType) {
        case UIWebViewNavigationTypeLinkClicked:
        {
            // 先检查是否遵循CDVYHInterfaceDelegate
            id <CDVYHInterfaceDelegate> yhif = nil;
            if ([self.viewController conformsToProtocol:@protocol(CDVYHInterfaceDelegate)]) {
                yhif = (id <CDVYHInterfaceDelegate>)self.viewController;
            } else {
                break;
            }
            
            return [yhif parseLink:urlString];
            
            break;
        }
//        case UIWebViewNavigationTypeFormSubmitted:
//        case UIWebViewNavigationTypeBackForward:
//        case UIWebViewNavigationTypeReload:
//        case UIWebViewNavigationTypeFormResubmitted:
//        case UIWebViewNavigationTypeOther:
        default:
            break;
    }
    
    return NO;
}

#pragma mark - Private
//- (void)

@end