본문 바로가기
프로그래밍/Xcode-iOS

WKWebView의 window.open과 alert처리 방법

by Mr-후 2020. 6. 26.
반응형
- (void)initWKWebView {
    
    CGFloat bottomPadding = 0.0f;
    CGFloat topPadding = 0.0f;
    
    UIWindow *window = UIApplication.sharedApplication.keyWindow;
    if (@available(iOS 11.0, *)) {
        topPadding = window.safeAreaInsets.top;
        bottomPadding = window.safeAreaInsets.bottom;
    }
    
    _createdWKWebViews = [NSMutableArray new];
    
    /**
     *웹뷰 바운스를 사용하지 않는 서비스는 웹뷰 높이를 탭바높이 만큼 빼고 잡는다.
     */
    CGFloat tabbarHeight = (!_hasWebViewBounce) ? [self getTabBarContextHeight] : bottomPadding;
    CGRect rect = self.view.bounds;
    rect.size.height = rect.size.height - tabbarHeight;
    
    self.wkWebView = [[WKWebView alloc] initWithFrame:rect]; //viewDidLoad에서 크기를 잡아준다.
    self.wkWebView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = YES;
    self.wkWebView.UIDelegate = self;
    [self.wkWebView setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
    [self.wkWebView setNavigationDelegate:self];
    [self.view addSubview:self.wkWebView];
    [self.wkWebView.scrollView setDelegate:self];
    [self.wkWebView.scrollView setBounces:_hasWebViewBounce];
}

WKWebView로 변경하고 발생되는 여러가지 이슈들이 있다. 우선 결제를 위한 window.open() 스크립트가 작동되지 않아 관련 리소스를 검색해서 보니 방법이 있다. 너무 쉽게 생각하고 덤벼 들었다는 생각이 들게 된 하루. 

우선 WKNavigationDelegate와 함께 반드시 구현해주어야 하는 WKUIDelegate 메서드들 중 일부를 추가해둔다. 

window.open()을 사용하기 위해서는 다음과 같은 WKUIDelegate메서드를 구현해야한다고 한다. 

- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
    WKUserContentController *userController = [[WKUserContentController alloc] init];

    NSString *script = @"var originalWindowClose=window.close;window.close=function(){var iframe=document.createElement('IFRAME');iframe.setAttribute('src','back://'),document.documentElement.appendChild(iframe);originalWindowClose.call(window)};";
    WKUserScript *userScript = [[WKUserScript alloc] initWithSource:script injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
    [userController addUserScript:userScript];
    
    configuration.preferences.javaScriptCanOpenWindowsAutomatically = YES;
    
    configuration.userContentController = userController;
    WKWebView *newWebView = [[WKWebView alloc] initWithFrame:self.wkWebView.frame configuration:configuration];
    newWebView.navigationDelegate = self;
    newWebView.UIDelegate = self;
    
    [self.view insertSubview:newWebView atIndex:1]; 
    return newWebView;
}

- (void)webViewDidClose:(WKWebView *)webView {
    NSLog(@"-- disClose"); 
    //호출되지 않음. 
}

처음 WKWebView를 초기화할 때 각 delegate에 self를 추가해주는게 중요하다. 

그리고 window.alert() 이 작동하지 않는 부분에 대해서는 예전에 UIWebView에서 카테고리로 확장해서 WebKit을 사용한 부분을 구현해주면 되는데 소스는 거의 똑같다. 아래 delegate 메서드를 구현하면 된다. 

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"알림"
                                                                             message:message
                                                                      preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:[UIAlertAction actionWithTitle:@"확인"
                                                        style:UIAlertActionStyleCancel
                                                      handler:^(UIAlertAction *action) {
                                                          completionHandler();
                                                      }]];
    [self presentViewController:alertController animated:YES completion:^{}];
}

 

반응형