Created
May 3, 2020 03:39
-
-
Save tyrad/b5abbc56a9b16393f988247ed9e3ee57 to your computer and use it in GitHub Desktop.
URLProtocol直接拦截wkwebview请求会有问题,一般推荐自定义scheme的方式
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSObject+NSURLProtocol_Wk.h | |
// URLProtocolDemo | |
// | |
// Created by panda on 2020/4/26. | |
// Copyright © 2020 quicktouch. All rights reserved. | |
// | |
#import <Foundation/Foundation.h> | |
NS_ASSUME_NONNULL_BEGIN | |
@interface NSURLProtocol (NSURLProtocol_Wk) | |
+ (void)wk_registerScheme:(NSString *)scheme; | |
+ (void)wk_unregisterScheme:(NSString *)scheme; | |
@end | |
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSObject+NSURLProtocol_Wk.m | |
// URLProtocolDemo | |
// | |
// Created by panda on 2020/4/26. | |
// Copyright © 2020 quicktouch. All rights reserved. | |
// | |
#import "NSURLProtocol+Wk.h" | |
#import <WebKit/WebKit.h> | |
FOUNDATION_STATIC_INLINE Class ContextControllerClass() { | |
static Class cls; | |
if (!cls) { | |
cls = [[[WKWebView new] valueForKey:@"browsingContextController"] class]; | |
} | |
return cls; | |
} | |
FOUNDATION_STATIC_INLINE SEL RegisterSchemeSelector() { | |
return NSSelectorFromString(@"registerSchemeForCustomProtocol:"); | |
} | |
FOUNDATION_STATIC_INLINE SEL UnregisterSchemeSelector() { | |
return NSSelectorFromString(@"unregisterSchemeForCustomProtocol:"); | |
} | |
@implementation NSURLProtocol (NSURLProtocol_Wk) | |
+ (void)wk_registerScheme:(NSString *)scheme { | |
Class cls = ContextControllerClass(); | |
SEL sel = RegisterSchemeSelector(); | |
if ([(id)cls respondsToSelector:sel]) { | |
// 放弃编辑器警告 | |
#pragma clang diagnostic push | |
#pragma clang diagnostic ignored "-Warc-performSelector-leaks" | |
[(id)cls performSelector:sel withObject:scheme]; | |
#pragma clang diagnostic pop | |
} | |
} | |
+ (void)wk_unregisterScheme:(NSString *)scheme { | |
Class cls = ContextControllerClass(); | |
SEL sel = UnregisterSchemeSelector(); | |
if ([(id)cls respondsToSelector:sel]) { | |
// 放弃编辑器警告 | |
#pragma clang diagnostic push | |
#pragma clang diagnostic ignored "-Warc-performSelector-leaks" | |
[(id)cls performSelector:sel withObject:scheme]; | |
#pragma clang diagnostic pop | |
} | |
} | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class WkUrlProtocolEx: URLProtocol, URLSessionDataDelegate, URLSessionTaskDelegate { | |
private var dataTask: URLSessionDataTask? | |
private var urlResponse: URLResponse? | |
private var receivedData: NSMutableData? | |
static var CustomKey: String { | |
return "myCustomKey" | |
} | |
// MARK: NSURLProtocol | |
override class func canInit(with request: URLRequest) -> Bool { | |
print(request.url ?? "") | |
if URLProtocol.property(forKey: WkUrlProtocolEx.CustomKey, in: request) != nil { | |
return false | |
} | |
return true | |
} | |
// override class func canInit(with task: URLSessionTask) -> Bool { | |
// return false | |
// } | |
override class func canonicalRequest(for request: URLRequest) -> URLRequest { | |
let mutableRequest = ((request as NSURLRequest).mutableCopy() as? NSMutableURLRequest)! | |
if let requestUrl = request.url { | |
print(requestUrl.absoluteString) | |
if requestUrl.absoluteString.hasPrefix("zy") || requestUrl.absoluteString.hasPrefix("ZY") { | |
// 简单测试使用 | |
let str = requestUrl.absoluteString | |
var reStr = str.replacingOccurrences(of: "zys:", with: "https:") | |
reStr = str.replacingOccurrences(of: "zy:", with: "http:") | |
mutableRequest.url = URL(string: reStr)! | |
} | |
} | |
// URLProtocol.setProperty(true, forKey: "", in: mutableRequest) | |
mutableRequest.addValue("Cookie_VALUE", forHTTPHeaderField: "Cookie") | |
return (mutableRequest as URLRequest) | |
} | |
override func startLoading() { | |
let newRequest = (self.request as NSURLRequest).mutableCopy() as! NSMutableURLRequest | |
print("加载远程资源:" + newRequest.url!.absoluteString) | |
URLProtocol.setProperty("true", forKey: WkUrlProtocolEx.CustomKey, in: newRequest) | |
let defaultConfigObj = URLSessionConfiguration.default | |
let defaultSession = URLSession(configuration: defaultConfigObj, delegate: self, delegateQueue: nil) | |
self.dataTask = defaultSession.dataTask(with: newRequest as URLRequest) | |
self.dataTask!.resume() | |
} | |
override func stopLoading() { | |
self.dataTask?.cancel() | |
self.dataTask = nil | |
self.receivedData = nil | |
self.urlResponse = nil | |
} | |
// MARK: NSURLSessionDataDelegate | |
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) { | |
self.client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) | |
self.urlResponse = response | |
self.receivedData = NSMutableData() | |
completionHandler(.allow) | |
} | |
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { | |
self.client?.urlProtocol(self, didLoad: data) | |
self.receivedData?.append(data) | |
} | |
// MARK: NSURLSessionTaskDelegate | |
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { | |
if error != nil { | |
self.client?.urlProtocol(self, didFailWithError: error!) | |
} else { | |
self.saveCachedResponse() | |
self.client?.urlProtocolDidFinishLoading(self) | |
} | |
// if error != nil, error!.code != NSURLErrorCancelled { | |
// self.client?.URLProtocol(self, didFailWithError: error!) | |
// } | |
} | |
// MARK: Private methods | |
/** | |
Do whatever with the data here | |
*/ | |
func saveCachedResponse() { | |
// refer to https://stackoverflow.com/questions/36297813/custom-nsurlprotocol-with-nsurlsession | |
// let timeStamp = NSDate() | |
// let urlString = self.request.url?.absoluteString | |
// let dataString = NSString(data: self.receivedData! as Data, encoding: String.Encoding.utf8.rawValue) as NSString? | |
// print("TimeStamp:\(timeStamp)\nURL: \(urlString)\n\nDATA:\(dataString)\n\n") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment