WkWebView instances and memory leak
After some research, I found my mistake:
let webConfig = WKWebViewConfiguration()
let userController:WKUserContentController = WKUserContentController()
userController.add(self, name: "interOp")
In viewDidLoad was causing memory leak, since that userController was never been released (and for the wkwebview, too).
My solution is: declare the WKUserContentController in the class of the viewController containing the wkWebView:
var userController: WKUserContentController = WKUserContentController()
reference to it in viewDidLoad:
userController.add(self, name: "interOp")
webConfig.userContentController = userController;
and release it in viewWillDisappear:
userController.removeScriptMessageHandler(forName: "interOp")
Maybe it is not the better way to manage this problem, but it works. When the view will be dismissed, it leave nothing in Safari and release his memory occupation:
Memory leak when using WKScriptMessageHandler
What you're seeing is a WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=136140. It was fixed in WebKit trunk a while ago, but does not appear to have been merged into any WebKit updates.
You can work around this by adding a -dealloc
to WKScriptMessage
that compensates for the over-retain. It could look something like this:
//
// WKScriptMessage+WKScriptMessageLeakFix.m
// TestWebkitMessages
//
// Created by Mark Rowe on 6/27/15.
// Copyright © Mark Rowe.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
// associated documentation files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial
// portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <mach-o/dyld.h>
#import <objc/runtime.h>
#import <WebKit/WebKit.h>
// Work around <https://webkit.org/b/136140> WKScriptMessage leaks its body
@interface WKScriptMessage (WKScriptMessageLeakFix)
@end
@implementation WKScriptMessage (WKScriptMessageLeakFix)
+ (void)load
{
// <https://webkit.org/b/136140> was fixed in WebKit trunk prior to the first v601 build being released.
// Enable the workaround in WebKit versions < 601. In the unlikely event that the fix is backported, this
// version check will need to be updated.
int32_t version = NSVersionOfRunTimeLibrary("WebKit");
int32_t majorVersion = version >> 16;
if (majorVersion > 600)
return;
// Add our -dealloc to WKScriptMessage. If -[WKScriptMessage dealloc] already existed
// we'd need to swap implementations instead.
Method fixedDealloc = class_getInstanceMethod(self, @selector(fixedDealloc));
IMP fixedDeallocIMP = method_getImplementation(fixedDealloc);
class_addMethod(self, @selector(dealloc), fixedDeallocIMP, method_getTypeEncoding(fixedDealloc));
}
- (void)fixedDealloc
{
// Compensate for the over-retain in -[WKScriptMessage _initWithBody:webView:frameInfo:name:].
[self.body release];
// Call our WKScriptMessage's superclass -dealloc implementation.
[super dealloc];
}
@end
Drop this in an Objective-C file in your project, set the compiler flags for this file to contain -fno-objc-arc
, and it should take care of the leak for you.
WKWebView crashes on deinit
Put this inside deinit method of child view controller:
webView.scrollView.delegate = nil
Related Topics
Detect App Launch from Widgetkit Widget Extension
Converting Int to Float Loses Precision for Large Numbers in Swift
Uicolor Colorwithred:Green:Blue:Alpha: Always Returns White Unless One Argument Is 0
How Can Split from String to Array by Chunks of Given Size
Responding to Ram Availability in iOS
Objective-C Wrapper for Cfunctionpointer to a Swift Closure
Nsgenericexception Reason Collection <Nsconcretemaptable: Xxx>
Uiimagejpegrepresentation Received Memory Warning
Get User Profile Details (Especially Email Address) from Twitter in iOS
iOS Facebook Sdk - Post Open Graph and Show on Timeline Without Clicking Activity Log
What Is the Swift Equivalent of Makeobjectsperformselector
Swift - Checking Unmanaged Address Book Single Value Property for Nil
Swift 3 JSON Nsfastenumerationiterator Has No Subscript Members
Combining 'And' and 'Or' Condition in Nspredicate
Swift - Fatal Error: Array Index Out of Range
Unarchive Array with Nskeyedunarchiver Unarchivedobject(Ofclass:From:)
How to Pass Data from Child to Parent View Controller? in Swift