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

UIWebView to WKWebView changed with Objective-C

by Mr-후 2020. 6. 25.
반응형

최근 애플 앱스토어에 심사를 제출할때마다 날라오는 안내 메일. 이제 곧 UIWebView를 사용하는 앱은 심사에서 거절될수있다는 안내다. 

2020/04/28 - [Programming/iOS] - ITMS-90809: Deprecated API Usage, new apps that use UIWebView as of April 30, 2020 and app updates that use UIWebView as of December 2020.

 

ITMS-90809: Deprecated API Usage, new apps that use UIWebView as of April 30, 2020 and app updates that use UIWebView as of Dece

조만간 앱을 업데이트 해야할 일이 있어 사전에 바이너리 업로드 테스트를 진행했다. 요즘은 Xcode도 최신을 유지해야 아카이빙해서 바로 업로드할 수 있다고 하길래... 뭐 앱이야 잘 올라갔는데

effectivecode.tistory.com

 

 

 

이걸 언제 교체를 하지..하지...하고 있다 어제 작업을 진행했다. 크게 무리없이 진행이 되었는데 외부 연동 포인터에서는 문제가 발생된 부분이 있어 고민이 생긴 셈이다. 

일단  UIWebView에서 WKWebView로 옮겨 가는 과정에 대한 절차를 정리한다. 

  1. WebKit프레임워크 추가 
  2. Import <WebKit/Webkit.h>
  3. 만약 현재 앱이 iOS11 이하의 버전을 지원하고 있다면 storyboard를 통해 WKWebView를 추가하는 것은 안된다. deploy target이 11이상일때 storyboard를 이용 가능하고 그렇지 않다면 코드 베이스에서 추가하는 것도 하나의 방법이다. 
  4. @property(strong, nonatomic) WKWebView *webView 
  5. ViewDidLoad에서 webView 초기화 및 addSubview 
  6. WKWebview의 delegate를 따른다고 추가  -> WKNavigationDelegate
    CGFloat tabbarHeight = 0.0f;
    CGRect rect = self.view.bounds;
    rect.size.height = rect.size.height - tabbarHeight;
    
    self.webView = [[WKWebView alloc] initWithFrame:rect]; //viewDidLoad에서 크기를 잡아준다.
    [self.webView setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
    [self.webView setNavigationDelegate:self];
    [self.view addSubview:self.webView];

7. 기존 UIWebView Delegate를 WKWebView의 WKNavigationDelegate를 추가 구현한다. 

#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    NSURL *url = navigationAction.request.URL;
    decisionHandler(WKNavigationActionPolicyAllow);
    
    NSString *reqUrl = [url absoluteString];
    NSLog(@" > load url = %@", reqUrl);
    NSLog(@" > all headerFields : %@", [navigationAction.request allHTTPHeaderFields]);
    if ([reqUrl isEqualToString:@"about:blank"]) {
        return;
    }
    

    //키보드 올림 방지 / 20.04.23
    [self.view endEditing:YES];

    if ([reqUrl hasPrefix:@"http"]) {
        if (IS_DEVE_MODE) { //개발모드일때 로드URL표시
            TOAST(reqUrl);
        }
    }
    
    //웹서비스간 이동을 위해 페이지
    if ([reqUrl hasPrefix:@"reload://"]) {
        [self loadUrl:[self.parser decodeParameter:[reqUrl stringByReplacingOccurrencesOfString:@"reload://" withString:@""]]];
        return;
    }
    
    if ([reqUrl hasPrefix:PREFIX_SCHEME]) {
        reqUrl = [reqUrl stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]; // 공백,리턴,라인 제거
        
        NSArray *requestArray = [reqUrl componentsSeparatedByString:@"://"];
        NSString *schemeData = [requestArray objectAtIndex:1];
        if ([requestArray count] > 2) {
            schemeData = [NSString stringWithFormat:@"%@://%@",requestArray[1],requestArray[2]];
        }
        
        BOOL hasResult = [_parser parsingScheme:schemeData];
        
        if (!hasResult) {
            NSLog(@" 잘못된 요청(필수 데이터) ");
            return;
        } else {
            BOOL hasProcessType = [self isFunctionType];
            if (!hasProcessType) {
                return;
            }
        }
        return;
    }
}

- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
    [self showIndicator];
}

- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, .5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void){
        [self hideIndicator];
    });
}

- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
    [self hideIndicator];
}

 

기존 UIWebView Delegate에서 다른 부분은 

decisionHandler(WKNavigationActionPolicyAllow); 부분과navigationAction.request 이부분을 활용하는 부분이 가장 두드러져보인다. 다른것까지 염두에 두고 이것 저것 해보지는 못했고 위의 예제 코드와 같이 했을 때, UIWebView로 구현했던 서비스 대부분이 해결되었다. 

 

문제가 발생한 부분은 다음이다. 

나이스 본인인증 결과 발급되는 Safe Key를 받아 처리하는 부분 역시 웹뷰로 구현을 했는데, 최종적으로 나이스 본인인증 후 POST로 발송되는 데이터 수신이 기존 UIWebView에서는 간단하게 (request.HTTPBODY) 받았다면 WKWebView에서는 navigationAction.request.HTTPBODY를 받을 수 없었다. WKWebView의 문제인지, POST를 발송하는 측의 문제인지 판단이 안선다. 

아직 이 문제는 해결하지 못했지만 앱 내에서 사용하는 UIWebView는 다 걷어냈다. 서비스에 문제가 없는지 어느정도 테스트 운영을 하면서 모니터링 후 앱 심사를 제출할 계획이다. 

 

 

반응형