我们正在为iOS构建浏览器。我们决定尝试使用自定义的NSURLProtocol
子类来实现我们自己的缓存方案并执行用户代理欺骗。它能够完成这两件事情......问题在于,导航到某些网站(msn.com是最糟糕的)会导致整个应用程序的用户界面冻结达15秒。显然有些东西阻塞了主线程,但它不在我们的代码中。NSURLProtocol + UIWebView +某些域=应用程序UI冻结
此问题只出现在UIWebView
和自定义协议的组合中。如果我们换一个WKWebView
(我们因各种原因不能使用),问题就消失了。同样,如果我们没有注册协议,以至于它没有被利用,问题就会消失。
它也似乎没有太大的问题什么协议;我们写了一个毫无意义的虚拟协议,只是转发响应(帖子的底部)。我们将该协议放入没有任何其他代码的裸机测试浏览器中 - 结果相同。我们也尝试使用别人的(RNCachingURLProtocol
)并观察到相同的结果。看起来,这两个组件与某些页面的简单组合会导致冻结。我无法尝试解决(甚至调查)此问题,并且非常感谢任何指导或提示。谢谢!
import UIKit
private let KEY_REQUEST_HANDLED = "REQUEST_HANDLED"
final class CustomURLProtocol: NSURLProtocol {
var connection: NSURLConnection!
override class func canInitWithRequest(request: NSURLRequest) -> Bool {
return NSURLProtocol.propertyForKey(KEY_REQUEST_HANDLED, inRequest: request) == nil
}
override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
return request
}
override class func requestIsCacheEquivalent(aRequest: NSURLRequest, toRequest bRequest: NSURLRequest) -> Bool {
return super.requestIsCacheEquivalent(aRequest, toRequest:bRequest)
}
override func startLoading() {
var newRequest = self.request.mutableCopy() as! NSMutableURLRequest
NSURLProtocol.setProperty(true, forKey: KEY_REQUEST_HANDLED, inRequest: newRequest)
self.connection = NSURLConnection(request: newRequest, delegate: self)
}
override func stopLoading() {
connection?.cancel()
connection = nil
}
func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
self.client!.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
}
func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
self.client!.URLProtocol(self, didLoadData: data)
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
self.client!.URLProtocolDidFinishLoading(self)
}
func connection(connection: NSURLConnection!, didFailWithError error: NSError!) {
self.client!.URLProtocol(self, didFailWithError: error)
}
}
嗨@Reid你找到了解决这个问题的方法吗?我也有同样的问题。 – Weizhi
@Reid,有什么消息吗?我有同样的问题。 –
我不是那个我遇到这个问题的项目(甚至在那家公司),所以没有在几个月内看过它。使用CustomHTTPProtocol示例代码(请参阅下面的@鲍里斯的答案)确实解决了这个问题,但我从来没有能够(a)完全隔离他们做了什么,或者(b)使他们的协议适应我需要做的事情......但其中一种方法是你最好的选择。 –