본문 바로가기
PROGRAMMING CODE/SWIFT

[SwiftUI] 다음(kakao) 주소찾기 part.2 (WKWebView, Sheet사용하기, Binding)

by daye_ 2023. 10. 19.

[전 블로그]

https://da-ye.tistory.com/221

 

[SwiftUI] 다음(kakao) 주소찾기 (WKWebView, 웹 통신)

스윽 보기엔 웹사이트 배포도 하고 첫 웹통신이라 꽤 어려워보였는데, 생각보다 하고나니 진종일 붙들고 있을 정도는 아니었다 아주 좋은 자료가 있는 줄 알았지만 ... 사람들이 극찬한 아래의

da-ye.tistory.com

 

이전 블로그에 이어 print가 잘 되는 모습을 보고,,,

성공했다는 확신에 차 있었다.

 

하지만.

 

 

 

(이전 포스팅의 웹 통신 스유 코드....)


KakaoWebController.swift

import SwiftUI
import WebKit

class KakaoWebController: NSObject, WKScriptMessageHandler {
    
    // didReceive, 데이터 받아오는 부분
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        
        if message.name == "callBackHandler", let data = message.body as? [String: Any] {
          if message.name == "callBackHandler" {
            print("message name : \(message.name)")
            print("post Message : \(message.body)")
        }
    }
}

struct WebView: UIViewRepresentable {
    let request: URLRequest
    private var webView: WKWebView?
    
    init(request: URLRequest) {
        self.webView = WKWebView()
        self.request = request
        self.webView?.configuration.userContentController.add(KakaoWebController(), name: "callBackHandler")
    
    }
    
    func makeUIView(context: Context) -> WKWebView {
        return webView!
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        uiView.load(request)
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }
    
    class Coordinator: NSObject, WKNavigationDelegate {
        let parent: WebView
        
        init(parent: WebView) {
            self.parent = parent
        }
    }
}

extension WebView {
    func callJS(_ args: Any = "") {
        webView?.evaluateJavaScript("postMessageToiOS('\(args)')") { result, error in
            if let error {
                print("Error \(error.localizedDescription)")
                return
            }
            
            if result == nil {
                print("It's void function")
                return
            }
            
            print("Received Data \(result ?? "")")
        }
    }
}

 

 

 

 

여기서 데이터를 받아와서 print 하긴 하는데 이게 생각 외로 전달이 안됐음

 

https://loann.tistory.com/49

 

SwiftUI, WKWebView 구현하기

import SwiftUI import WebKit struct ContentView: View { let url = "https://google.com" // showAlert가 true면 알림창이 뜬다 // If showAlert is true, a notification window pops up @State var showAlert: Bool = false // alert에 표시할 내용 // Thi

loann.tistory.com

여기 블로그를 보고 따라치면 무조건 될 줄 알았는데 아니었다 ㅜ,ㅜ

바인딩 부분에서 빨간색 수 많은 줄이 늘어나고,,,,,,,

 

 

 

 


KakaoData.Swift

class kakaoData: ObservableObject {
	@Published var message

	func receivedMessage(data: string){
    		message = data
   	}
}

 

 

 

기억은 잘 안나지만 이런식으로 class를 하나 더 짜서

userContentController 내부에서 데이터를 받아오니 receivedMessage를 print대신 호출해줬다.

 

객체를 생성하니, 객체가 따로 노는것같아서

싱글톤으로 또 만들어줬는데 싱글톤이 왜 class 내부의 변수를 못가져오는지 의문 가득,,

 

그러다가 바인딩을 왜 못쓰는지 알아냈다!!!

 

 

[최종 코드]

import SwiftUI
import WebKit

class KakaoWebController: NSObject, WKScriptMessageHandler {
    @Binding var showingWebSheet: Bool
    
    init(showingWebSheet: Binding<Bool>) {
        self._showingWebSheet = showingWebSheet
    }
    
    // didReceive, 데이터 받아옴
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        
        if message.name == "callBackHandler", let data = message.body as? [String: Any] {
            print("message name : \(message.name)")
            print("post Message : \(message.body)")
            
            showingWebSheet.toggle()
        }
    }
   
}

struct WebView: UIViewRepresentable {
    let request: URLRequest
    private var webView: WKWebView?
    @Binding var showingWebSheet: Bool
    
    init(request: URLRequest, showingWebSheet: Binding<Bool>, ) {
        self.webView = WKWebView()
        self.request = request
        self._showingWebSheet = showingWebSheet
        self.webView?.configuration.userContentController
            .add(KakaoWebController(showingWebSheet: _showingWebSheet), name: "callBackHandler")
    }
    
    func makeUIView(context: Context) -> WKWebView {
        return webView!
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        uiView.load(request)
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }
    
    class Coordinator: NSObject, WKNavigationDelegate {
        let parent: WebView
        
        init(parent: WebView) {
            self.parent = parent
        }
    }
}

extension WebView {
    func callJS(_ args: Any = "") {
        webView?.evaluateJavaScript("postMessageToiOS('\(args)')") { result, error in
            if let error {
                print("Error \(error.localizedDescription)")
                return
            }
            
            if result == nil {
                print("It's void function")
                return
            }
            
            print("Received Data \(result ?? "")")
        }
    }
}

init()에 추가해주고

self.showingWebSheet = $showingWebSheet으로 선언하면 될 줄 알았는데

self._showingWebSheet = showingWebSheet으로 선언을 해 주어야 한다고 한다.

 

 

 

combine ; underBar
self._momentDate // Binding<Date> -> struct 그 자체
self.momentDate // self._momentDate.wrappedValue와 같다.
self.$momentDate // Binding<Date> -> self._momentDate.projectedValue와 같음
//child view에서 변수에 접근해서, date의 값을 바꿔야 할 때 전달해줄 때

라고함.!! 언더바는 C언어의 포인터느낌

 

 

 

이렇게 하면 sheet바인딩 외, 데이터 바인딩까지 가능!

행복

 

 

 

 

[데이터 변환, 위도, 경도받기]

 

[SwiftUI] 다음(kakao) 주소찾기 part.3 (WKWebView, 위도, 경도 받기, 데이터 변환)

[지난 포스팅] [SwiftUI] 다음(kakao) 주소찾기 part.1 (WKWebView, 웹 통신) 스윽 보기엔 웹사이트 배포도 하고 첫 웹통신이라 꽤 어려워보였는데, 생각보다 하고나니 진종일 붙들고 있을 정도는 아니었다

da-ye.tistory.com

 

 

 

 

 

[그 외 참고한 블로그]

https://www.swiftyplace.com/blog/loading-a-web-view-in-swiftui-with-wkwebview