bundleid修改后ocr插件ExCardSDK不能使用的解决办法

 

原理和上篇文章一样 :  https://blog.csdn.net/qq_15509071/article/details/102688400

 

这里直接贴代码

 

#import "NSBundle+yyy.h"
#import <objc/runtime.h>
@implementation NSBundle (yyy)
+ (void)load{
    
//    NSString *bundleid = [[self mainBundle] bundleIdentifier];
    
      {
    
        Method originalMethod = class_getInstanceMethod([NSBundle class], @selector(bundleIdentifierS));
        Method swizzledMethod = class_getInstanceMethod([NSBundle class], @selector(bundleIdentifier));
        method_exchangeImplementations(originalMethod, swizzledMethod);
    
    }
    {
        Method originalMethod = class_getInstanceMethod([NSBundle class], @selector(infoDictionaryS));
        Method swizzledMethod = class_getInstanceMethod([NSBundle class], @selector(infoDictionary));
        method_exchangeImplementations(originalMethod, swizzledMethod);
        
    }
//    {
//        Method originalMethod = class_getInstanceMethod([NSBundle class], @selector(localizedInfoDictionaryS));
//        Method swizzledMethod = class_getInstanceMethod([NSBundle class], @selector(localizedInfoDictionary));
//        method_exchangeImplementations(originalMethod, swizzledMethod);
//
//    }
}
- (NSDictionary*)infoDictionaryS{
    NSMutableDictionary *dicc = [self infoDictionaryS].mutableCopy;
    if ([Global sharedData].useHookBundleid == YES) {
        [dicc setObject:@"需要的" forKey:@"CFBundleIdentifier"];
    }
    return dicc;
}
- (NSString *)bundleIdentifierS{
    if ([Global sharedData].useHookBundleid == YES) {
        return @"需要的";
    }else{
        return [self bundleIdentifierS];
    }
}

 

 

识别身份证的调用方法

    [EXOCRCardEngineManager initEngine];
    self.manager = [EXOCRQuadRecoManager sharedManager:、];
    [self.manager setDisplayLogo:NO];
    [self.manager setRecoTimeout:90];
    setCustomScanView
    [self.manager recoQuadCardFromStreamByCustomScanViewWithCardType:EXOCRCardTypeIDCARD];



协议方法
/**
 *  @brief   识别完成,获取识别结果
 *  @param   info - 识别结果模型
 */
-(void)recoCompleted:(id)info;{
    //识别成功后的操作
    [self.manager dismissScanViewControllerAnimated:YES];
}

initEngine 里面写 useHookBundleid = YES;

由于协议方法是在实现的类里实现的,所以useHookBundleid = No,不能按照之前的思路。

方法1:识别成功都调用了dismissScanViewControllerAnimated:YES,在这个方法里加上。但如果没调用就会有问题

@implementation EXOCRQuadRecoManager (YYY)
+ (void)load{
//    {
//        Method originalMethod = class_getInstanceMethod([self class], @selector(dismissScanViewControllerAnimated:));
//        Method swizzledMethod = class_getInstanceMethod([self class], @selector(dismissScanViewControllerAnimatedS:));
//        method_exchangeImplementations(originalMethod, swizzledMethod);
//
//    }
}
//扫描身份证结束
//-(void)dismissScanViewControllerAnimatedS:(BOOL)animated;{
//
//    [Global sharedData].useHookBundleid = NO;
//
//    [self dismissScanViewControllerAnimatedS:animated];
//}

方法2:参考:https://www.jianshu.com/p/2d9774c8b224 对代理方法hook。哪个类实现了代理给哪个类替换方法。

@interface EXOCRQuadRecoManager (YYY)
@end

@implementation EXOCRQuadRecoManager (YYY)
+ (void)load{
    {
//交换的是设置代理的方法
        Method originalMethod = class_getInstanceMethod([self class], @selector(setCustomScanView:));
        Method swizzledMethod = class_getInstanceMethod([self class], @selector(setCustomScanViewS:));
        method_exchangeImplementations(originalMethod, swizzledMethod);
        
    }

}

- (BOOL)setCustomScanViewS:(UIView *)customScanView{
    BOOL isSc =  [self setCustomScanViewS:customScanView];
    dz_exchangeMethod([customScanView class], @selector(recoCompleted:), [self class], @selector(recoCompletedS:),@selector(orirecoCompleted:));
    return isSc;
}

- (void)recoCompletedS:(UIWebView *)webView
{
    [Global sharedData].useHookBundleid = NO;
    [self recoCompletedS:webView];
}


static void dz_exchangeMethod(Class originalClass, SEL originalSel, Class replacedClass, SEL replacedSel, SEL orginReplaceSel){
    // 原方法
    Method originalMethod = class_getInstanceMethod(originalClass, originalSel);
    // 替换方法
    Method replacedMethod = class_getInstanceMethod(replacedClass, replacedSel);
    // 如果没有实现 delegate 方法,则手动动态添加
    if (!originalMethod) {
        Method orginReplaceMethod = class_getInstanceMethod(replacedClass, orginReplaceSel);
        BOOL didAddOriginMethod = class_addMethod(originalClass, originalSel, method_getImplementation(orginReplaceMethod), method_getTypeEncoding(orginReplaceMethod));
        if (didAddOriginMethod) {
            NSLog(@"did Add Origin Replace Method");
        }
        return;
    }
    // 向实现 delegate 的类中添加新的方法
    // 这里是向 originalClass 的 replaceSel(@selector(replace_webViewDidFinishLoad:)) 添加 replaceMethod
    BOOL didAddMethod = class_addMethod(originalClass, replacedSel, method_getImplementation(replacedMethod), method_getTypeEncoding(replacedMethod));
    if (didAddMethod) {
        // 添加成功
        NSLog(@"class_addMethod_success --> (%@)", NSStringFromSelector(replacedSel));
        // 重新拿到添加被添加的 method,这里是关键(注意这里 originalClass, 不 replacedClass), 因为替换的方法已经添加到原类中了, 应该交换原类中的两个方法
        Method newMethod = class_getInstanceMethod(originalClass, replacedSel);
        // 实现交换
        method_exchangeImplementations(originalMethod, newMethod);
    }else{
        // 添加失败,则说明已经 hook 过该类的 delegate 方法,防止多次交换。
        NSLog(@"Already hook class --> (%@)",NSStringFromClass(originalClass));
    }
}
@end

 

 

 

 

 

 

 

 

 

 

 

 

 

下面是另一种使用方法

 

需要用到的地方:身份证识别     
    [Global sharedData].useHookBundleid = YES;
 
    [EXOCRCardEngineManager initEngine];

    self.manager = [EXOCRQuadRecoManager sharedManager:self.controller];
    
    [self.manager recoQuadCardParticularFromStreamWithCardType:EXOCRCardTypeIDCARD OnParticularCompleted:^(int statusCode, id cardInfo) {
        [Global sharedData].useHookBundleid = NO;
        //。。。
    } OnCanceled:^(int statusCode) {
        [Global sharedData].useHookBundleid = NO;
        
    } OnFailed:^(int statusCode, UIImage *recoImg) {
        [Global sharedData].useHookBundleid = NO;
        
    }];

这样也是每一个地方都要写。简化一下

在上边的类中添加如下代码

        {
            Method originalMethod = class_getInstanceMethod([self class], @selector(recoQuadCardParticularFromStreamWithCardType:OnParticularCompleted:OnCanceled:OnFailed:));
            Method swizzledMethod = class_getInstanceMethod([self class], @selector(recoQuadCardParticularFromStreamWithCardType:OnParticularCompleted:OnCanceled:OnFailedS:));
            method_exchangeImplementations(originalMethod, swizzledMethod);
    
        }


-(void)recoQuadCardParticularFromStreamWithCardType:(EXOCRCardType)cardType

                              OnParticularCompleted:(EXOCRCompletedQuadCardParticularBlock)completedBlock

                                         OnCanceled:(EXOCRCanceledBlock)EXOCRCanceledBlock

                                           OnFailedS:(EXOCRFailedBlock)EXOCRFailedBlock;{
    [self recoQuadCardParticularFromStreamWithCardType:cardType OnParticularCompleted:^(int statusCode, id cardInfo) {
        [Global sharedData].useHookBundleid = NO;
        completedBlock(statusCode,cardInfo);

    } OnCanceled:^(int statusCode) {
        [Global sharedData].useHookBundleid = NO;

        EXOCRCanceledBlock(statusCode);

    } OnFailedS:^(int statusCode, UIImage *recoImg) {
        [Global sharedData].useHookBundleid = NO;

        EXOCRFailedBlock(statusCode,recoImg);

    }];
    
}

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值