iOS 拦截篇(一):拦截H5通过标签选取的图片

一、场景

H5经常会需要选择手机照片来完善自身内容;比如上传身份证照片、资产照片等等等。有时候这些照片经常需要app处理完后才上传给H5,那么这时候作为app的你就必须先处理好H5选择的手机照片,再上传给他。所以本文接下来将讲解如何拦截处理H5选择的手机照片;

二、基础知识准备

普及基础知识:
H5选择手机照片的方式主要有两种:

  • 1、通过与app的JS交互,选择手机照片;
  • 2、通过H5自身的标签,选择手机照片;

第一种JS交互的,图片数据的获取太容易处理了,就不再这里讲了。我们这边主要讲H5通过H5自身的标签,选择手机照片。

三、拦截方法

这里我们先讲怎么实现,下一点再介绍思路。
实现方式很简单

1、添加已CJFileUploadPanel类

pod 'CJHook/CJFileUploadPanel'
CJFileUploadPanel类源码

image.png

2、建立DemoFileUploadPanel类,使用CJFileUploadPanel提供的接口实现你拦截后的图片处理。

DemoFileUploadPanel.h

#import 

@interface DemoFileUploadPanel : NSObject

+ (void)startHook;
+ (void)stopHook;

@end

DemoFileUploadPanel.m

#import "DemoFileUploadPanel.h"
#import 
#import "DemoCacheUtil.h"

@implementation DemoFileUploadPanel

+ (void)startHook {
    __weak typeof(self)weakSelf = self;
    [CJFileUploadPanel startHookWithAbsoluteFilePathHandle:^NSString *(UIImage *originImage) {
        NSData *newImageData = [weakSelf dealImage:originImage];![分割图1.jpg](https://upload-images.jianshu.io/upload_images/6214155-49f701e7162b8ec8.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

        
        // 保存图片到本地
        NSString *absoluteFilePath = [DemoCacheUtil saveImageData:newImageData forModuleType:DemoModuleTypeIot];
        
        sleep(5); //用来测试是否主线程是否会被阻塞(请在选择图片后,选择返回,看是否卡住)
        
        return absoluteFilePath;
    }];
}

+ (void)stopHook {
    [CJFileUploadPanel stopHook];
}


+ (NSData *)dealImage:(UIImage *)image {
    UIImage *newImage = [UIImage imageNamed:@"饮品2.jpg"];
    NSData *newImageData = UIImagePNGRepresentation(newImage);
    return newImageData;
}


@end

3、调用

略。

如果你还想了解思路或者原理,请往下看,如果只是想使用的话,到这里就可以了。


分割图1.jpg

四、拦截的思路分析

拦截的思路:1、拦截、替换系统方法;2、在新方法中按产品需求处理图片;
详细步骤如下。

1、拦截、替换系统方法

即:将在WKFileUploadPanel中实现的UIImagePickerController代理方法imagePickerController:didFinishPickingMediaWithInfo:替换为你在其他类中写的其他方法。因为系统没提供WKFileUploadPanel这个类给你来让你在该类中直接写交换的方法。
所以我们这里是将其替换为你在CJHookFileUploadPanel类中实现的- (void)swizzled_imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info方法。
通过此步,你就能够在新写的方法- (void)swizzled_imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info里面获取到图片选择器选取到的图片数据了。

@implementation CJHookFileUploadPanel

+ (void)hookFileUploadPanel:(BOOL)hook {
    SEL originalSelector = @selector(imagePickerController:didFinishPickingMediaWithInfo:);
    SEL swizzledSelector = @selector(swizzled_imagePickerController:didFinishPickingMediaWithInfo:);
    Class originalClass = NSClassFromString(@"WKFileUploadPanel");
    Class otherClass = [CJHookFileUploadPanel class];
    if (hook) {
        bool success = HookCJHelper_exchangeOriMethodToNewMethodWhichAddFromDiffClass(originalClass, originalSelector, otherClass, swizzledSelector);
        NSLog(@"exchangeOriMethodToNewMethod:%@", success ? @"success": @"failure");
    } else {
        bool success = HookCJHelper_recoverOriMethodToNewMethodWhichAddFromDiffClass(originalClass, originalSelector, otherClass, swizzledSelector);
        NSLog(@"recoverOriMethodToNewMethod:%@", success ? @"success": @"failure");
    }
}

- (void)swizzled_imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    NSMutableDictionary *new_info = [[NSMutableDictionary alloc] initWithDictionary:info];
   // 在这里按产品需求处理图片得到新new_info......
    
    [self swizzled_imagePickerController:picker didFinishPickingMediaWithInfo:new_info];
}

@end

上述为某类添加另一个类中的方法的实现代码详见HookCJHelper
HookCJHelper源码

image.png

结束语

感谢阅读!

你可能感兴趣的:(iOS 拦截篇(一):拦截H5通过标签选取的图片)