달력

5

« 2024/5 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
2021. 11. 11. 11:58

webview_flutter로 alert/confirm 띄우기 (iOS) 개발/Flutter2021. 11. 11. 11:58

반응형

이전에도 비슷한 주제로  글을 작성한 적이 있었는데 이번엔 해결법이 약간 다르다.

(이전 글 : https://risha-lee.tistory.com/40)

 

이번에는 상황이 Confirm 종류도 많았고,

그냥 웹뷰를 보여주는 앱이었으며
웹은 이미 작성된지 오래된 상태였고

Confirm 이후 분기 처리도 꽤 복잡한 편이어서 꼭 웹의 Confirm 기능을 써야만 했다.

 

일단 Android는 webview_flutter를 2.0.13으로 버전 업하니 alert가 기본으로 작동하게 되었는데 

iOS에서는 여전히 alert/confirm이 안뜨는 문제가 있었다.

찾아보니 역시나 webview_flutter 자체 지원은 안되고 파일 업로드 때 처럼 직접 소스 코드를 수정하기로 하였다.

 

1. 먼저 webview_flutter가 저장되는 위치를 찾는다.

나는 mac 환경이고 webview_flutter 버전은 2.0.13을 사용하였기 때문에

/Users/${userId}/.pub-cache/hosted/pub.dartlang.org/webview_flutter-2.0.13

여기에 저장되어 있었다.

 

2. webview_flutter-2.0.13/ios/Classes/FlutterWebView.m 의 맨 하단 @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:@"OK" 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{
  //    DLOG(@"msg = %@ frmae = %@",message,frame);
  UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
  [alertController addAction:([UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
    completionHandler(NO);
  }])];
  [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    completionHandler(YES);
  }])];

    UIViewController *_viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
  [_viewController presentViewController:alertController animated:YES completion:nil];
}

 

 

runJavaScriptTextInputPanelWithPrompt라고 prompt 처리하는 것으로 보이는 것도 있긴한데

내가 작업하는 웹뷰에서 사용하지 않아서 확인하진 못하였으나 비슷한 방식으로 변환하면 다음과 같다.

- (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];
}

 

 

 

참고 출처 : https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/695084/

https://stackoverflow.com/questions/6131205/how-to-find-topmost-view-controller-on-ios

반응형
:
Posted by 리샤씨
반응형

며칠 전, Flutter에서 webview_flutter(https://pub.dev/packages/webview_flutter)로 띄운 소스에서

alert가 보이지 않으니 해결해달라는 요청을 받아 처리하게 되었습니다.

찾아보니 webview_flutter는 alert&confirm을 지원하지 않는다고 합니다.

flutter와 html에서 약속을 해서 새로운 function을 만들고 호출하는 방법도 있지만,

(참조: https://cording-cossk3.tistory.com/103)

저는 html 개발하시는 분과 직접 소통하는 것도 아니고, 최대한 네이티브 소스는 건드리지 않기 위하여

그냥 기존에 있는 alert를 flutter의 toast로 작업하는 방식으로 처리하였습니다.

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:toast/toast.dart';
import 'package:webview_flutter/webview_flutter.dart';

class WebviewPage extends StatelessWidget {
  WebViewController _webViewController;

  @override
  void initState() {
    if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
  }

  @override
  Widget build(BuildContext context) {
    return WebView(
      initialUrl: '${yourUrl}',
      javascriptMode: JavascriptMode.unrestricted,
      javascriptChannels: <JavascriptChannel>{
        _alertJavascriptChannel(context),
      },
      onWebViewCreated: (WebViewController webViewController) {
        _webViewController = webViewController;
      },
      onPageFinished: (url) async {
        try {
          var javascript = '''
                             window.alert = function (e){
                               Alert.postMessage(e);
                             }
                           ''';
          await _webViewController?.evaluateJavascript(javascript);
        } catch (_) {}
      },
    );
  }

  JavascriptChannel _alertJavascriptChannel(BuildContext context) {
    return JavascriptChannel(
        name: 'Alert',
        onMessageReceived: (JavascriptMessage message) {
          Toast.show(message.message, context,
              duration: Toast.LENGTH_LONG,
              gravity: Toast.CENTER,
              backgroundColor: Colors.black38,
              backgroundRadius: 5);
        });
  }
}

이 방법으로 하면 confirm도 처리되긴 합니다.

그런데 confirm이 하나일땐 크게 문제 없겠지만 (위와 같이 confirm을 정의해서 flutter 내에서 dialog 호출해서 처리)

여러 개일때는 confirm마다 기능이 다르다면 결국 html 개발자와 같이 상의해서 개발해야 할 것입니다.

confirm도 처리해야 할 때는 android는 webview_flutter를 2.0.13 버전 이상으로 업 하면 해결됩니다.

ios는 다음 글을 참고하여 처리하여 주세요. (다음 글 : https://risha-lee.tistory.com/42)

 

 

참고 출처 : https://github.com/flutter/flutter/issues/30358

 

 

 

 

 

 

 

반응형
:
Posted by 리샤씨


반응형
반응형