-
-
Save prep4gmat/eac0a7ce2ef006ed339d9966c14e5828 to your computer and use it in GitHub Desktop.
Crash when reallocating WKWebView
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
import UIKit | |
import WebKit | |
import XWebView | |
class LeakAvoider : NSObject, WKScriptMessageHandler { | |
weak var delegate : WKScriptMessageHandler? | |
init(delegate:WKScriptMessageHandler) { | |
self.delegate = delegate | |
super.init() | |
} | |
func userContentController(userContentController: WKUserContentController, | |
didReceiveScriptMessage message: WKScriptMessage) { | |
self.delegate?.userContentController( | |
userContentController, didReceiveScriptMessage: message) | |
} | |
deinit { | |
print("leak avoider deinit") | |
print("self = \(self.debugDescription)") | |
} | |
} | |
class PracticeWebView: WKWebView, UIGestureRecognizerDelegate { | |
func configHandlers(messageHandler: WKScriptMessageHandler?, tag: Int) { | |
if let handler = messageHandler { | |
let leakHandler = LeakAvoider(delegate: handler) | |
configuration.userContentController.addScriptMessageHandler(leakHandler, name: "choiceTapped") | |
configuration.userContentController.addScriptMessageHandler(leakHandler, name: "sizeNotification") | |
configuration.userContentController.addScriptMessageHandler(leakHandler, name: "pageLoaded") | |
configuration.userContentController.addScriptMessageHandler(leakHandler, name: "imageTapped") | |
// Get script that's to be injected into the document | |
let fastclickScript:WKUserScript = WKUserScript(source: jsStringFromFileName("fastclick"), injectionTime: WKUserScriptInjectionTime.AtDocumentEnd, forMainFrameOnly: false) | |
configuration.userContentController.addUserScript(fastclickScript) | |
let longPressScript:WKUserScript = WKUserScript(source: jsStringFromFileName("longPress"), injectionTime: WKUserScriptInjectionTime.AtDocumentEnd, forMainFrameOnly: false) | |
configuration.userContentController.addUserScript(longPressScript) | |
} | |
let mainJSScript:WKUserScript = WKUserScript(source: jsStringFromFileName("main"), injectionTime: WKUserScriptInjectionTime.AtDocumentEnd, forMainFrameOnly: false) | |
configuration.userContentController.addUserScript(mainJSScript) | |
let scrollJS = "function scrollTo(element, to, duration) { var start = element.scrollTop, change = to - start, currentTime = 0, increment = 20; var animateScroll = function(){ currentTime += increment; var val = Math.easeInOutQuad(currentTime, start, change, duration); element.scrollTop = val; if(currentTime < duration) { setTimeout(animateScroll, increment); } }; animateScroll(); } Math.easeInOutQuad = function (t, b, c, d) { t /= d/2; if (t < 1) return c/2*t*t + b; t--; return -c/2 * (t*(t-2) - 1) + b; };" | |
let scrollScript:WKUserScript = WKUserScript(source: scrollJS, injectionTime: WKUserScriptInjectionTime.AtDocumentEnd, forMainFrameOnly: false) | |
configuration.userContentController.addUserScript(scrollScript) | |
//notify | |
let pageLoadedJSString = "window.onload = function () {window.scrollBy(0, 0); window.webkit.messageHandlers.pageLoaded.postMessage({width: document.width, height: document.height, tag: \(tag)});};" | |
let pageLoadedNotificationJS:WKUserScript = WKUserScript(source: pageLoadedJSString, injectionTime: WKUserScriptInjectionTime.AtDocumentEnd, forMainFrameOnly: false) | |
configuration.userContentController.addUserScript(pageLoadedNotificationJS) | |
let sizeNotificationJSString = "MathJax.Hub.Register.StartupHook('Begin Typeset',function(){console.log('begin')}),MathJax.Hub.Register.StartupHook('End Typeset',function(){console.log('end typeset')}),MathJax.Hub.Register.StartupHook('End',function(){console.log('End');var e=document.getElementsByClassName('math-jax-content');for(console.log(e),j=0;j<e.length;j++){var t=e[j];t.className+=' math-jax-loaded'};window.scrollBy(0, 0); window.webkit.messageHandlers.sizeNotification.postMessage({width: document.width, height: document.height, tag: \(tag)});});" | |
let sizeNotificationJS:WKUserScript = WKUserScript(source: sizeNotificationJSString, injectionTime: WKUserScriptInjectionTime.AtDocumentEnd, forMainFrameOnly: false) | |
configuration.userContentController.addUserScript(sizeNotificationJS) | |
} | |
// Button Click Script to Add to Document | |
func jsStringFromFileName(name: String, directory: String? = nil) ->String { | |
let results = FileUtils.read(name, type:"js", directory: directory ?? "commonHtmlTemplates") | |
return results.content! | |
} | |
deinit { | |
print("webview deinit") | |
print("self = \(self.debugDescription)") | |
} | |
func scrollToTop() { | |
evaluateJavaScript("scrollTo(document.body, 0, 0);", completionHandler: nil) | |
} | |
override func layoutSubviews() { | |
scrollToTop() | |
let scrollSize = CGSizeMake(frame.width, frame.height) | |
scrollView.contentSize = scrollSize | |
print("scrollview width = \(scrollView.contentSize.width)") | |
} | |
} | |
extension WKWebView { | |
public func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? { | |
return nil | |
} | |
} |
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
var webView = PracticeWebView() | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
webView.configHandlers(self, tag: 0) | |
webView.translatesAutoresizingMaskIntoConstraints = false | |
webView.navigationDelegate = self | |
webView.scrollView.delegate = self | |
view.addSubview(webView) | |
let VFLViews = ["webView":webView] | |
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[webView]|", options:NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: VFLViews)) | |
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[webView]|", options:NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: VFLViews)) | |
} | |
override func viewWillDisappear(animated: Bool) { | |
super.viewWillDisappear(animated) | |
webView.stopLoading() | |
webView.configuration.userContentController.removeScriptMessageHandlerForName("choiceTapped") | |
webView.configuration.userContentController.removeScriptMessageHandlerForName("sizeNotification") | |
webView.configuration.userContentController.removeScriptMessageHandlerForName("pageLoaded") | |
webView.configuration.userContentController.removeScriptMessageHandlerForName("imageTapped") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment