Безопасно ли использовать + load в динамической структуре для быстрой настройки wknavigationdelegate?

Я настраиваю простой 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

Это безопасно, или + загружается слишком рано, чтобы пробовать что-то подобное? В моем тестировании я не заметил никаких проблем с ним, но после прочтения этот блог Майка Эша он сказал, что использование + load опасно / сложно.

Конкретно из блога:

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.

Рискну ли я здесь, если не использую @autoreleasepool? Я не понимаю, как добавить

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

помогает мне здесь.

Кстати: пул автозапуска необходим, потому что + load работает вне цикла выполнения. Автоматического автоматического выпуска пула нет.

bbum 10.08.2018 21:27
1
1
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

+load полон опасностей и хрупкости. Мне приходилось выслеживать много забавных ошибок из-за сюрпризов +load на протяжении десятилетий. В общем, этого следует избегать. И при использовании он должен касаться минимального количества остальной части системы, особенно потому, что вы измените порядок, в котором вещи инициализируются во время выполнения.

Я бы порекомендовал вам иметь какой-то крючок инициализации в вашей структуре, который клиенты вашей платформы должны вызывать в приложении, обычно во время метода didFinishLaunching:.... делегата приложения.

Вы можете вставить assert()s в другие пути кода, которые могут предупреждать или вызывать, если фреймворк не был должным образом инициализирован.

Спасибо за это - я собираюсь использовать ловушку инициализации, как было предложено. У меня был кто-то, кто жаловался на сбой (сообщение отправляется на нулевой тип MyDelegate). Я все еще пытаюсь понять ситуацию, в которой это происходит, потому что сам не могу ее воспроизвести. Видимо каким-то образом, когда система пытается запустить метод делегата webView:didFinishNavigation, мой объект делегата уже был освобожден. Я предполагаю, что это как-то связано с тем фактом, что метод делегата запускается из основного цикла выполнения, но я установил делегат вне основного цикла выполнения.

Adam Johns 12.08.2018 22:01

Или, может быть, проблема в том, что я не устанавливаю _defaultWebView.navigationDelegate обратно в ноль, когда устанавливаю _myDelegate в ноль. И система пытается позже запустить другой метод делегата в веб-просмотре.

Adam Johns 12.08.2018 22:15

Другие вопросы по теме