일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- androidstudio
- 개발자
- Xcode
- UIKit
- button
- PyQt5
- PyQt
- Chrats
- Apple
- Chart
- ios
- cocoapods
- kotlin
- ui
- Swift
- Python
- 개발
- 어플리케이션
- Android
- UIButton
- alamofire
- charts
- graph
- Storyboard
- TableView
- 라이브러리
- UITableView
- 그래프
- modal
- library
- Today
- Total
Jiwift
[iOS/Swift] WebKit, window.open을 통해서 새로운 탭 열기 feat.nice 본인 인증. window.close 본문
[iOS/Swift] WebKit, window.open을 통해서 새로운 탭 열기 feat.nice 본인 인증. window.close
지위프트 2023. 6. 21. 22:14정답이 아닐 수 있습니다. 각자 상황에 맞는 방법을 찾아서 사용하시면 됩니다.
인터넷을 하다보면 새로운 창이 필요할 때가 있습니다. Nice 본인인증과 같은 상황이조.
근데 우리가 사용하는 앱들은 창이 여러개가 보여지지 않습니다.
대부분 사용하는 앱들은 회원가입을 진행하거나 물건을 구매할때 순차적으로 진행되는 화면을 보게됩니다.
PC 환경 처럼 새로운 창을 띄우는 경우는 드물다고 봅니다.(기획에 따라 다름)
근데.. 역시 예외 상황은 꼭 생기고 PC 환경 처럼 새로운 탭을 열어서 작업이 필요한 경우가 있습니다. 이유는 모릅니다.
한가지 상황을 생각해봅시다. 어딘가에 회원가입을 웹뷰로 만드는 서비스가 있다고 생각합니다.
(회원가입 부분은 프론트엔드 개발자가, 네이티브 WebKit과 브릿지 확인은 iOS 개발자가 하는 상황입니다. )
근데 어찌저찌 하다보니 Nice 본인 인증을 위해서는 새로운 창을 띄어야합니다. PC 환경 처럼 말이지요. 근데 iOS만 맨날 개발하던 개발자는 당황합니다. WebKit은 하나인데 어떻게 화면을 더 띄우지?? 라는 고민을 하게되조. 다행이 구글은 많은 것을 알고 있고 해결법도 있었습니다.
iOS 개발자는 웹을 모릅니다. 그저 vue로 만들어진 회원가입 화면에서 'window.open'라는 명령어를 보내면 새로운 창이 뜬다는 것만 알고있습니다.
다행이 iOS는 그 신호를 캐치할 수 있습니다.
동작이 안된다는 글도있지만 정책 관련된거라 잘 모르겠습니다. 제가 구현했을 땐 동작하니깐요.
요약
1. 코드를 통해 웹뷰 두개를 옵셔널로 생성
2. 회원가입 웹뷰 먼저 설정하고 add
3. window.open하면 웹에서 받은 데이터로 nice 웹뷰 설정 및 add
4. 완료되면 닫기 (window.close 혹은 브릿지를 통해서)
우선 저는 WebKit을 코드로 생성할 것입니다.
WebKit이 담기는 View를 하나 Storyboard로 생성하고 login 화면을 위한 WebKit과 Nice 화면을 위한 WebKit을 생성합니다.
(변수명은 마음대로)
// 로그인 웹킷
private func initLoginWk(url: String) {
// 로그인 WebKit 초기화
self.loginWKView = nil
// 웹뷰에 필요한 설정 및 설정값을 추가로 적용합니다.
let webConfiguration = WKWebViewConfiguration()
// 화면 열기
webConfiguration.preferences.javaScriptCanOpenWindowsAutomatically = true
// 로그인 웹뷰 브릿지 추가
webConfiguration.userContentController.add(self, name: "bridge")
// 자바 스크립트 허용
if #available(iOS 14.0, *) {
webConfiguration.defaultWebpagePreferences.allowsContentJavaScript = true
} else {
// Fallback on earlier versions
webConfiguration.preferences.javaScriptEnabled = true
}
// 로그인 WebKit을 생성해서 변수에 넣음
self.loginWKView = WKWebView(frame: self.webKitContainer.bounds, configuration: webConfiguration)
// 웹뷰 화면 플렉서블하게 적용
self.loginWKView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// Delegate 등록
self.loginWKView?.navigationDelegate = self
self.loginWKView?.uiDelegate = self
// 링크 미리보기 차단
self.loginWKView?.allowsLinkPreview = false
// Web 띄우기
self.initUrl(url: url)
// Container에 WebKit 추가
self.webKitContainer.addSubview(self.loginWKView!)
}
그리고 위와 같이 코드를 작성합니다. 여기서 많은 것들을 설정했지만 WebKit 메소드 설명은 따로 검색해서 보시고 ..
코드 흐름을 보면 configuration을 생성해 옵션과 함께 처음에 생성한 webkit에 넣어줍니다.
그리고 initUrl함수를 통해서 웹페이지 로드를 하고 WebKit이 담길 webKitContainer에 addSubview합니다.
(initUrl은 제가 만든 것이니 굳이 따라하실 필요없습니다. 그냥 웹킷 load 함수에요)
// 화면 열기
webConfiguration.preferences.javaScriptCanOpenWindowsAutomatically = true
// Delegate 등록
self.loginWKView?.uiDelegate = self
이것만 빼먹지 않으면 됩니다.
자바스크립트 코드로 화면을 여는 것을 허용해주는 것과 delegate인데 이 둘이 다합니다.
ViewController에 WKUIDelegate도 상속합니다.
// window.open
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
// 기존 웹뷰 브릿지 제거
self.loginWKView?.configuration.userContentController.removeScriptMessageHandler(forName: "bridge")
// WebView Size
let frame = UIScreen.main.bounds
// 파라미터로 받은 configuration
self.niceWebView = WKWebView(frame: frame, configuration: configuration)
// 오토레이아웃 처리
self.niceWebView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// 링크 미리보기 차단
self.niceWebView?.allowsLinkPreview = false
// Nice 웹뷰 브릿지 추가
self.niceWebView?.configuration.userContentController.add(self, name: "bridge")
// 화면에 추가
self.webKitContainer.addSubview(self.niceWebView!)
return self.niceWebView!
}
이번에는 window.open이 발생했을 때 WebKit이 수행하는 Delegate 함수 중 하나입니다.
// 파라미터로 받은 configuration
self.niceWebView = WKWebView(frame: frame, configuration: configuration)
configuration은 delegate에서 받고 그외 넣고 싶은 옵션을 넣어줍니다. 그리고 위에서 생성한 niceWebView에 넣어줍니다.
그러고 마찬가지로 WebKit이 담길 webKitContainer에 addSubview합니다.
우리는 총 두개의 웹킷을 사용해서 window.open을 수행했습니다.
func webViewDidClose(_ webView: WKWebView) {
niceWebView?.removeFromSuperview()
niceWebView = nil
}
해당 코드를 작성하면 웹에서 window.close를 수행했을때 네이티브에서 동작하고 싶은 코드를 실행할 수 있습니다.
nice화면을 닫고싶어서 SuperView에서 지우고 nil처리를 했습니다.
위와 같이 구성하면 브릿지를 따로 주어야합니다. 아니면 하나의 브릿지만 사용해서 add하고 remove해도됩니다.
[iOS/Swift] 웹뷰 브릿지 등록, WebKit과 브릿지, userContentController, 데이터 전송 (tistory.com)
WKWebView에서 자바스크립트로 window.open(), window.close() 하는 경우 처리 (github.com)
iOS 팝업 정책과 window.open (velog.io)