美文网首页
iOS WebView加载自定义资源-图片

iOS WebView加载自定义资源-图片

作者: Wynter_Wang | 来源:发表于2019-08-13 16:54 被阅读0次

    现在很多项目中都有嵌套H5,但有些功能让H5来做用户体验不是很好,那么这部分功能就需要使用js和客户端交互来完成 。最近开发了图片选择器提供给前端使用,在用户选择完图片后客户端将沙盒路径传给js,用于展示选中的图片。

    /private/var/mobile/Containers/Data/Application/3861D884-D098-4F33-BA90-22BDF9D84F9B/Documents/chooseImages/5731BBA0-C6A2-48A4-94F7-A29A2A97F3DA.png
    
    

    很显然前端不能加载沙盒路径的图片

    那么如何让前端支持加载沙盒图片呢?

    解决方法就是自定义协议,然后拦截实现协议以达到前端加载客户端本地图片的目的。

    1、自定义CustomURLProtocol继承NSURLProtocol

    #import "CustomURLProtocol.h"
    
    @interface CustomURLProtocol(){
        NSURLRequest *request;
    }
    
    @end
    // 协议名
    static NSString *const hasInitKey = @"webImage";
    
    @implementation IRCCustomURLProtocol
    
    + (BOOL)canInitWithRequest:(NSURLRequest *)request {
        if ([request.URL.scheme caseInsensitiveCompare:hasInitKey] == NSOrderedSame) {
            return YES;
        }
        return NO;
    }
    
    - (void)startLoading {
        NSURLResponse *response = [[NSURLResponse alloc] initWithURL:request.URL MIMEType:@"image/png" expectedContentLength:-1 textEncodingName:nil];
        NSString *imgPath = [NSString stringWithFormat:@"%@%@", self.request.URL.host, self.request.URL.path];
        NSData *data = [NSData dataWithContentsOfFile:imgPath];
        
        [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
        [[self client] URLProtocol:self didLoadData:data];
        [[self client] URLProtocolDidFinishLoading:self];
        NSLog(@"start loading !");
    }
    

    2、在AppDelegate中注册协议

    [NSURLProtocol registerClass:[CustomURLProtocol class]];
    
    

    3、前端加载图片

    <img style="width: 100px;height:100px;" id="image" src="webImage://private/var/mobile/Containers/Data/Application/3861D884-D098-4F33-BA90-22BDF9D84F9B/Documents/chooseImages/5731BBA0-C6A2-48A4-94F7-A29A2A97F3DA.png" />
    
    

    这种解决方法只在UIWebView中起作用,WKWebView在iOS 11之前是没有办法加载本地资源的。

    WKWebView不支持NSURLProtocol如何解决?

    通过查看WebKit源码发现在源码中存在注册自定义的方法只是没有开放,使用WKBrowsingContextController类中的registerSchemeForCustomProtocol:方法可以注册自定义协议,那么我们可以自定义一个Category来实现自定义协议注册,核心代码:

    + (void)wk_registerScheme:(NSString *)scheme {
        Class cls = NSClassFromString(@"browsingContextController")
        SEL sel = NSSelectorFromString(@"registerSchemeForCustomProtocol:");
        if ([(id)cls respondsToSelector:sel]) {
            [(id)cls performSelector:sel withObject:scheme];
        }
    }
    

    具体使用参考大牛的解决方法,传送门:WKURLSchemeHandler,有人反映使用私有API会APP Store被拒,项目中使用此方法目前成功上线。

    iOS 11 新增WKURLSchemeHandler实现 (Swift)

    import UIKit
    import WebKit
    
    class CustomWKURLSchemeHandler: NSObject, WKURLSchemeHandler, UINavigationControllerDelegate,UIImagePickerControllerDelegate {
        
        var task: WKURLSchemeTask?
        
        
        func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
            task = urlSchemeTask
            let picker = UIImagePickerController()
            picker.delegate = self
            picker.sourceType = .photoLibrary
            let viewController =  webView.next as! ViewController
            viewController.present(picker, animated: true, completion: nil)
        }
        
        func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
           task = nil
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            picker.dismiss(animated: true)
            guard let task = task else { return }
            let image = info[.originalImage] as! UIImage
            let data = image.pngData()
            
            let response = URLResponse(url: task.request.url!, mimeType: "image/png", expectedContentLength: -1, textEncodingName: nil)
            task.didReceive(response)
            task.didReceive(data!)
            task.didFinish()
        }
    }
    
    let configuration = WKWebViewConfiguration()
    configuration.setURLSchemeHandler(CustomWKURLSchemeHandler(), forURLScheme: "webImage")
    let webView = WKWebView(frame: .zero, configuration: configuration)
    let request = URLRequest(url: URL(string: "http://localhost:8080/b/file.html")!)
    webView.load(request)
    view = webView
    
    
    <h2>这是一张图片</h2>
    <img style="width: 200px;height:200px;" id="image1" src="" /><br/>
    <button style="width: 200px;height:40px;" onclick="btnAction()">加载路径</button>
    <script>
        function btnAction() {
            var imagePathStr = "webImage://imagePath.png";
            document.getElementById("image1").src = imagePathStr;
            alert(imagePathStr);
        }
    </script>
    
    

    总结

    • 相同路径的资源,代理或自定义协议只会执行一次,再次加载不会触发代理或自定义协议方法

    相关文章

      网友评论

          本文标题:iOS WebView加载自定义资源-图片

          本文链接:https://www.haomeiwen.com/subject/ztzdrctx.html