iOS WKScriptMessageHandler循环引用解决
2019-11-01 本文已影响0人
某非著名程序员
问题:在使用WKWebView时与h5交互时,监听了h5的事件,让h5可以调用OC方法。退出页面后发现WKWebView没有被释放。
CMWebWeakScriptMessageDelegate * scriptMsgDelegate = [[CMWebWeakScriptMessageDelegate alloc] initWithDelegate:self];
WKUserContentController *userContentController = [[WKUserContentController alloc] init];
[userContentController addScriptMessageHandler:scriptMsgDelegate name:WEBVIEW_CLOSE_ACTION];
1.循环引用的原因
循环引用CMWKWebView持有了WKWebViewConfiguration,而WKWebViewConfiguration持有了WKUserContentController。在添加事件时addScriptMessageHandler,WKUserContentController有强持有了CMWKWebView。导致了循环引用。
2.经典的解决方案:
对于系统的这种循环引用,我们只要断开其中一环即可。
增加一个中间类去弱引用CMWKWebView,断开环即可。CMWebWeakScriptMessageDelegate的代码:
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface CMWebWeakScriptMessageDelegate : NSObject<WKScriptMessageHandler>
@property (nonatomic, weak) id<WKScriptMessageHandler> scriptDelegate;
- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;
@end
NS_ASSUME_NONNULL_END
#import "CMWebWeakScriptMessageDelegate.h"
@implementation CMWebWeakScriptMessageDelegate
- (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
总结:
1.NSTimer循环引用大同小异,解决方案可参考:如何优雅的解决NSTimer释放问题
2.有任何问题欢迎留言交流