ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [flutter] webview 사용할 때 아이폰, 아이패드에서 alert 창 활성화 되지 않는 현상
    flutter/flutter 기타 등등 2023. 5. 26. 20:07

     

    flutter_webview 를 이용해서 내부에서 사용중인 사이트를 불러왔는데 alert 이 활성화 되지 않는 현상이 나타났습니다.

     

    안드로이드는 되는데 아이폰, 아이패드에서만 안되네요.

     

    webview 라이브러리에서 추가하는 방법은 찾지 못해서 iOS 에 추가하는 방법을 적용하였습니다.

     

     

    1. flutter 프로젝트에서 iOS 코드를 Xcode 로 오픈

    2. Pods > Development Pods > webview_flutter_kwwebview >...>C lasses > FWFUIDelegateHostApi.m 선택

    3. FWFUIDelegateHostApi.m 파일 @implementation FWFUIDelegate 와 @end 사이에 내용을 추가해줍니다. 추가할 내용은 아래에 있습니다.

    < 기존 코드 >

    @implementation FWFUIDelegate
    - (instancetype)initWithBinaryMessenger:(id<FlutterBinaryMessenger>)binaryMessenger
                            instanceManager:(FWFInstanceManager *)instanceManager {
      self = [super initWithBinaryMessenger:binaryMessenger instanceManager:instanceManager];
      if (self) {
        _UIDelegateAPI = [[FWFUIDelegateFlutterApiImpl alloc] initWithBinaryMessenger:binaryMessenger
                                                                      instanceManager:instanceManager];
      }
      return self;
    }
    
    - (WKWebView *)webView:(WKWebView *)webView
        createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
                   forNavigationAction:(WKNavigationAction *)navigationAction
                        windowFeatures:(WKWindowFeatures *)windowFeatures {
      [self.UIDelegateAPI onCreateWebViewForDelegate:self
                                             webView:webView
                                       configuration:configuration
                                    navigationAction:navigationAction
                                          completion:^(FlutterError *error) {
                                            NSAssert(!error, @"%@", error);
                                          }];
      return nil;
    }
    @end

     

    < 추가할 코드 >

    - (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:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
      completionHandler();
      }])];
    
        UIViewController *_viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
      [_viewController presentViewController:alertController animated:YES completion:nil];
    }
    
    - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
      UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
      [alertController addAction:([UIAlertAction actionWithTitle:@"취소" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
      }])];
      [alertController addAction:([UIAlertAction actionWithTitle:@"확인" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
      }])];
    
        UIViewController *_viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
      [_viewController presentViewController:alertController animated:YES completion:nil];
    }
    
    - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{
      UIAlertController *alertController = [UIAlertController alertControllerWithTitle:prompt message:@"" preferredStyle:UIAlertControllerStyleAlert];
      [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.text = defaultText;
      }];
      [alertController addAction:([UIAlertAction actionWithTitle:@"" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(alertController.textFields[0].text?:@"");
      }])];
      UIViewController *_viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
      [_viewController presentViewController:alertController animated:YES completion:nil];
    }

     

    < 내용 추가 완료한 코드 >

    @implementation FWFUIDelegate
    - (instancetype)initWithBinaryMessenger:(id<FlutterBinaryMessenger>)binaryMessenger
                            instanceManager:(FWFInstanceManager *)instanceManager {
      self = [super initWithBinaryMessenger:binaryMessenger instanceManager:instanceManager];
      if (self) {
        _UIDelegateAPI = [[FWFUIDelegateFlutterApiImpl alloc] initWithBinaryMessenger:binaryMessenger
                                                                      instanceManager:instanceManager];
      }
      return self;
    }
    
    - (WKWebView *)webView:(WKWebView *)webView
        createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
                   forNavigationAction:(WKNavigationAction *)navigationAction
                        windowFeatures:(WKWindowFeatures *)windowFeatures {
      [self.UIDelegateAPI onCreateWebViewForDelegate:self
                                             webView:webView
                                       configuration:configuration
                                    navigationAction:navigationAction
                                          completion:^(FlutterError *error) {
                                            NSAssert(!error, @"%@", error);
                                          }];
      return nil;
    }
    
    - (void)webView:(WKWebView *)webView
        requestMediaCapturePermissionForOrigin:(WKSecurityOrigin *)origin
                              initiatedByFrame:(WKFrameInfo *)frame
                                          type:(WKMediaCaptureType)type
                               decisionHandler:(void (^)(WKPermissionDecision))decisionHandler
        API_AVAILABLE(ios(15.0)) {
      [self.UIDelegateAPI
          requestMediaCapturePermissionForDelegateWithIdentifier:self
                                                         webView:webView
                                                          origin:origin
                                                           frame:frame
                                                            type:type
                                                      completion:^(WKPermissionDecision decision) {
                                                        decisionHandler(decision);
                                                      }];
    }
    
    - (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:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
      completionHandler();
      }])];
    
        UIViewController *_viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
      [_viewController presentViewController:alertController animated:YES completion:nil];
    }
    
    - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
      UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
      [alertController addAction:([UIAlertAction actionWithTitle:@"취소" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
      }])];
      [alertController addAction:([UIAlertAction actionWithTitle:@"확인" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
      }])];
    
        UIViewController *_viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
      [_viewController presentViewController:alertController animated:YES completion:nil];
    }
    
    - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{
      UIAlertController *alertController = [UIAlertController alertControllerWithTitle:prompt message:@"" preferredStyle:UIAlertControllerStyleAlert];
      [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.text = defaultText;
      }];
      [alertController addAction:([UIAlertAction actionWithTitle:@"" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(alertController.textFields[0].text?:@"");
      }])];
      UIViewController *_viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
      [_viewController presentViewController:alertController animated:YES completion:nil];
    }
    @end

     

    FWFUIDelegateHostApi.m 파일 안에 코드를 추가해주고 다시 실행해보면 alert 실행이 가능합니다.

     

     

     

     

     

    댓글

Designed by Tistory.