Is it safe to use +load in a dynamic framework to set up a quick WKNavigationDelegate?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



Is it safe to use +load in a dynamic framework to set up a quick WKNavigationDelegate?



I'm setting up a simple WKNavigationDelegate in my dynamic framework to get WKWebView's default user agent string:


WKNavigationDelegate


WKWebView


@interface MyDelegate: NSObject <WKNavigationDelegate>
@end

static NSString *_defaultUserAgent;
static WKWebView *_defaultWebView;
static MyDelegate *_myDelegate;

@implementation MyDelegate
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation
DispatchHelper.runOnMain = ^
[_defaultWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id __nullable userAgent, NSError * __nullable error)
_defaultUserAgent = userAgent;
_defaultWebView = nil;
_myDelegate = nil;
];
;

@end

@implementation WKWebView (Util)

+ (void)load
_myDelegate = MyDelegate.new;
WKWebView *wkWebView = WKWebView.new;
wkWebView.navigationDelegate = _myDelegate;
[wkWebView loadHTMLString:@"<HTML><BODY>TEST</BODY></HTML>" baseURL:nil];
_defaultWebView = wkWebView;


@end



Is this safe, or is +load too early to try something like this? In my testing I haven't noticed any issues with it, but after reading this Mike Ash blog, he says using +load is dangerous/tricky.



Specifically from the blog:



Keep in mind that there's no autorelease pool present at loading time
(usually) so you'll need to wrap your code in one if you're calling
into Objective-C stuff.



Am I at risk here by not using @autoreleasepool? I'm confused on how adding


+ (void)load
@autoreleasepool
_myDelegate = MyDelegate.new;
WKWebView *wkWebView = WKWebView.new;
wkWebView.navigationDelegate = _myDelegate;
[wkWebView loadHTMLString:@"<HTML><BODY>TEST</BODY></HTML>" baseURL:nil];
_defaultWebView = wkWebView;




helps me here.





BTW: The autorelease pool is needed because +load runs outside of a run loop. There is no automatic autoreleasepool in place.
– bbum
Aug 10 at 19:27




1 Answer
1



+load is rife with danger and fragility. I have had to track down many a fun bug due to +load surprises over the decades. In general, it should be avoided. And when used, it should touch a minimal amount of the rest of the system specifically because you'll be changing the order within which things are initialized at runtime.


+load


+load



I would recommend that you have some kind of initialization hook in your framework that your framework's clients are expected to call in the app, typically during the app delegate's didFinishLaunching:.... method.


didFinishLaunching:....



You can put in assert()s along other code paths that can warn or raise if the framework was not properly initialized.


assert()s





Thanks for this - I'm gonna go with an initialization hook as suggested. I did have someone complaining about a crash (message being sent to null MyDelegate type). I'm still trying to understand the situation for that occurring as I can't reproduce it myself. Apparently somehow when the system tries to fire the webView:didFinishNavigation delegate method, my delegate object has already been deallocated. I'm guessing this has something to do with the fact that the delegate method is fired from the main run loop, but I set up the delegate outside of the main run loop.
– Adam Johns
Aug 12 at 20:01


MyDelegate


webView:didFinishNavigation





Or maybe the issue is I'm not setting _defaultWebView.navigationDelegate back to nil when I set _myDelegate to nil. And the system is attempting to fire another delegate method on the webview later.
– Adam Johns
Aug 12 at 20:15


_defaultWebView.navigationDelegate


_myDelegate






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard