YHInjectConfigManager.m 4.79 KB
//
//  YHInjectJsCordovaManager.m
//  YH_Explorer
//
//  Created by 孙凯 on 2018/5/15.
//

#import "YHInjectConfigManager.h"


@implementation SchmeModel4wk

- (instancetype)copyWithZone:(NSZone *)zone {
    SchmeModel4wk *model = [[SchmeModel4wk allocWithZone:zone] init];
    model.className  = self.className;
    model.schemeName = self.schemeName;
    
    return model;
}

@end

@interface YHInjectConfigManager()

//设置自定义 scheme 处理
@property (nonatomic,strong) NSArray <SchmeModel4wk *> *schemeArray;
@property (nonatomic,copy)NSString *jsCordova;

@end
@implementation YHInjectConfigManager

/**
 * @abstract
 * 返回初始化好的单例
 *
 * @return 返回的单例
 */
+ (instancetype)sharedInstance{
    static YHInjectConfigManager *sharedInstance = nil;
    
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        sharedInstance = [[YHInjectConfigManager alloc] init];
    });
    return sharedInstance;
}
#pragma mark - Private
/**
 *  动态注入Js
 *
 *  @param resource js的名称
 */
- (BOOL)injectJavascript:(NSString *)resource webView:(UIWebView*)webView{
    if(!self.jsCordova) {
        NSString *jsPath = [[NSBundle mainBundle] pathForResource:resource ofType:@"js"];
        self.jsCordova = [NSString stringWithContentsOfFile:jsPath encoding:NSUTF8StringEncoding error:NULL];
    }
    
    //用cordova.version判断cordova是否注入成功
    NSString* jsCordovaVersion = [NSString stringWithFormat:@"cordova.version"];
    NSString* res = [webView stringByEvaluatingJavaScriptFromString:jsCordovaVersion];
    if (res != nil && res.length > 0) {
        return TRUE;
    }
    
    NSLog(@"injectJavascript uiwebview");
    //注入cordova js 代码
    [webView stringByEvaluatingJavaScriptFromString:self.jsCordova];
    
    //再次判定是否已经注入
    res = [webView stringByEvaluatingJavaScriptFromString:jsCordovaVersion];
    
    if (res != nil && res.length > 0) {
        return TRUE;
    }
    return FALSE;
}

/**
 @brief 循环注入直到成功
 
 @since 1.0.2
 */
- (void)cycleInject:(UIWebView*)webView {
    
    BOOL bSuc = NO;
    // 向网页中注入cordova
    bSuc = [self injectJavascript:@"cordova" webView:webView];
        
    if (!bSuc) {
        __weak typeof(self) weakSelf = self;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [weakSelf cycleInject:webView];
        });
        
    }
}


- (void)cycleInjectWKWebView:(WKWebView *)webView
{
    if(!self.jsCordova) {
        NSString *jsPath = [[NSBundle mainBundle] pathForResource:@"cordova" ofType:@"js"];
        self.jsCordova = [NSString stringWithContentsOfFile:jsPath encoding:NSUTF8StringEncoding error:NULL];
    }
    
    if (self.jsCordova.length == 0) {
        return;
    }
    
    WKUserContentController *userContentController = webView.configuration.userContentController;
    NSMutableArray<WKUserScript *> *array = [userContentController.userScripts mutableCopy];
    WKUserScript *injectUserScript = nil;
    for (WKUserScript *wkUScript in array) {
        if ([wkUScript.source isEqual:self.jsCordova]) {
            injectUserScript = wkUScript;
            break;
        }
    }
    
    if (!injectUserScript) {
        injectUserScript = [[WKUserScript alloc] initWithSource:self.jsCordova injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [userContentController addUserScript:injectUserScript];
        NSLog(@"injectJavascript wkwebview success");
    }
}


- (void)mockLocalURLResource:(NSArray <SchmeModel4wk *> *)array {
    self.schemeArray = [array filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(SchmeModel4wk *  _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
        if ([evaluatedObject isKindOfClass:[SchmeModel4wk class]]
             && NSClassFromString(evaluatedObject.className)) {
            return YES;
        } else {
            return NO;
        }
    }]];
}

- (void)unMockLocalURLResource {
    @synchronized (self.schemeArray) {
        if (self.schemeArray.count > 0) {
            self.schemeArray = [NSArray array];
        }
    }
}

- (void)registerURLSchemeHandler:(WKWebViewConfiguration *)config {

    NSArray *resultArray = nil;
    @synchronized (self.schemeArray) {
        resultArray = [self.schemeArray copy];
    }

    for (SchmeModel4wk *item in resultArray) {
        if (item.className.length > 0 && item.schemeName.length > 0) {
            Class class = NSClassFromString(item.className);
            if (class) {
                if (@available(iOS 11.0, *)) {
                    [config setURLSchemeHandler:[class new] forURLScheme:item.schemeName];
                } else {
                    // Fallback on earlier versions
                }
            }
        }
    }
}


@end