您的位置:首页 > 移动开发

iOS开发--- WKWebView导致Controller不调用dealloc

2017-04-26 11:12 567 查看
导读:本文主要解决WKWebView在通过WKUserContentController添MessageHandler方法用于JS调用Native导致ViewController内存泄露,无法正常释放。

1.ViewController没有调用dealloc可能的原因

在使用WKWebView时,ViewController在该释放的时候没有释放(没有调用
- (void)dealloc
方法)。参考了这篇文章检查了ViewController中的NSTimer、delegate并将所有block中的self更换为weakSelf,结果仍然没有调用dealloc方法。

之后检查了ViewController中所有使用到self的地方,发现WKUserContentController的下面这个方法有使用到self:
App注册方法用于JS调用

- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name


WKWebViewConfiguration *wkConfig = [[WKWebViewConfiguration alloc] init];
wkConfig.userContentController = [[WKUserContentController alloc] init];
[wkConfig.userContentController addScriptMessageHandler:self name:@"Native"];


所以Google了一下该方法是否会引起ViewController不调用dealloc方法。确实是由于该方法引起ViewController内存泄漏。
搜到的结果

2. 解决方案

(1)WeakScriptMessageDelegate

可以创建一个新的类WeakScriptMessageDelegate,也可以将@interface-@end写在ViewController.h中,@implementation-@end写在ViewController.m中。

@interface WeakScriptMessageDelegate : NSObject<WKScriptMessageHandler>

@property (nonatomic, weak) id<WKScriptMessageHandler> scriptDelegate;

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;

@end


@implementation WeakScriptMessageDelegate

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate {
self = [super init];
if (self) {
_scriptDelegate = scriptDelegate;
}
return self;
}

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
[self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
}

@end


(2)使用

添加了下面这行代码之后ViewController就会调用dealloc方法,此时ViewController已经正常释放。但是WeakScriptMessageDelegate没有释放,需要在dealloc中将WeakScriptMessageDelegate释放掉。

WKWebViewConfiguration *wkConfig = [[WKWebViewConfiguration alloc] init];
wkConfig.userContentController = [[WKUserContentController alloc] init];
[wkConfig.userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"Native"];


(3)释放WeakScriptMessageDelegate

- (void)dealloc {
[self.wkConfig.userContentController removeScriptMessageHandlerForName:@"Native"];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: