๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ’ป Programming/iOS

[iOS] WKWebView๋กœ ์›น๋ทฐ(WebView) ๊ตฌํ˜„ํ•˜๊ธฐ

by ๊ธฐ๋ฌด์ • 2025. 2. 24.
728x90

 

 

 

WebView

WebView๋ž€ ํ”„๋ ˆ์ž„์›Œํฌ์— ๋‚ด์žฅ๋œ ์›น ๋ธŒ๋ผ์šฐ์ € ์ปดํฌ๋„ŒํŠธ๋กœ View์˜ ํ˜•ํƒœ๋กœ ์•ฑ์— ์ž„๋ฒ ๋”ฉํ•˜๋Š” ๊ฒƒ์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, API๋ฅผ ํ†ตํ•ด์„œ ๋ฐ›์€ URL์„ ํ˜ธ์ถœ์„ ํ•ด๋ณด๋ฉด ์‘๋‹ต ๊ฐ’์œผ๋กœ JSON, XML ๊ฐ™์€ ๋ฐ์ดํ„ฐ ํฌ๋งท์ด ์•„๋‹ˆ๋ผ HTML๋กœ ๋“ค์–ด์˜ต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ด๋ ‡๊ฒŒ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์˜ค๊ฒŒ ๋˜๋ฉด ํŒŒ์‹ฑ์„ ํ•ด์ค„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
 
๊ทธ๋ž˜์„œ ์ด๋Ÿฌํ•œ HTML ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•ด์„œ ์›นํŽ˜์ด์ง€๋กœ ๋ณด์—ฌ์ฃผ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ WebView์ž…๋‹ˆ๋‹ค.

์ฆ‰, WebView๋Š” ์•ฑ ๋‚ด์— ์›น ํŽ˜์ด์ง€๋ฅผ ๋„ฃ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 


WebView๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

UIWebView

UIWebView๋Š” ios 2.0์— ์ถœ์‹œ๋˜์—ˆ์œผ๋ฉฐ ์›น ์ฝ˜ํ…์ธ ๋ฅผ ์•ฑ ๋‚ด๋ถ€์—์„œ ๋ Œ๋”๋ง์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ฑ๋Šฅ๊ณผ ๋ณด์•ˆ ๋ฌธ์ œ๋กœ ์ธํ•ด iOS 12์—์„œ Deprecated๋˜์–ด iOS 13๋ถ€ํ„ฐ WKWebView๋กœ ๋Œ€์ฒด๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

 

WKWebView

ios 8.0์ด์ƒ์˜ WebKit ๊ธฐ๋ฐ˜ ์›น๋ทฐ์ž…๋‹ˆ๋‹ค. ๊ธฐ์กด์˜ UIWebView๋ณด๋‹ค ํ›จ์”ฌ ๋น ๋ฅด๊ณ  ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์ด ์ตœ์ ํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, ์›น ์ฝ˜ํ…์ธ ๋ฅผ ๋ณ„๋„์˜ ํ”„๋กœ์„ธ์Šค์—์„œ ์‹คํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•ˆ์ •์ ์ž…๋‹ˆ๋‹ค. ์ด ๋ง์€ ์ฆ‰์Šจ, ์›น ํŽ˜์ด์ง€๋Š”์™€ ์•ฑ์˜ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ณ„๋„๋กœ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์›น ํŽ˜์ด์ง€์˜ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์•„๋ฌด๋ฆฌ ํฌ๋”๋ผ๋„ ์•ฑ์ด ์ฃฝ์ง€ ์•Š๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 

์ด์™ธ์—๋„ JavaScript ์‹คํ–‰ ์†๋„๊ฐ€ ๋น ๋ฅด๋ฉฐ ์ฟ ํ‚ค๋‚˜ ์บ์‹œ, ์„ธ์…˜ ๋“ฑ ์›น ๋ธŒ๋ผ์šฐ์ง• ๊ธฐ๋Šฅ์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์–ด ์•ฑ ๋‚ด๋ถ€์—์„œ ์›น์„ ์™„์ „ํžˆ ์ปจํŠธ๋กคํ•ด์•ผ ํ•  ๋•Œ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

 

 

SFSafariView

SFSafariView ๋Š” ios 9.0๋ถ€ํ„ฐ ์‚ฌ์šฉ๋˜์—ˆ์œผ๋ฉฐ, Safari ๊ธฐ๋ฐ˜์˜ ์›น๋ทฐ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ์•ฑ ๋‚ด์—์„œ ์‚ฌํŒŒ๋ฆฌ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋„์šฐ๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‚ฌํŒŒ๋ฆฌ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋„์šฐ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœ์ž๊ฐ€ ์›น ์ฝ˜ํ…์ธ ๋ฅผ ์ง์ ‘ ์ปจํŠธ๋กคํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

 

SFSafariView๋Š” ๋กœ๊ทธ์ธ ์œ ์ง€, Safari ์ฟ ํ‚ค ๋ฐ ๋ฐ์ดํ„ฐ ๋“ฑ ๊ณต์œ  ๋“ฑ ๋‹ค์–‘ํ•œ ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

WKWebView๊ฐ€ ๋‹จ์ˆœํžˆ ์›น ํŽ˜์ด์ง€ ํ•˜๋‚˜๋งŒ์„ ๋ณด์—ฌ์ค€๋‹ค๋ฉด, SFSafariView๋Š” ์‚ฌํŒŒ๋ฆฌ์˜ ๊ธฐ๋Šฅ์„ ์ด์šฉํ•  ์ˆ˜๊ฐ€ ์žˆ์–ด ๋‹ค์–‘ํ•œ ๋™์ž‘์ด ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค.

 

 

ASWebAuthenticationSession

iOS 12 ์ด์ƒ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋ฉฐ OAuth ์ธ์ฆ(๋กœ๊ทธ์ธ)์— ํŠนํ™”๋œ WebView ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž์˜ ๊ธฐ์กด ์‚ฌํŒŒ๋ฆฌ ๋กœ๊ทธ์ธ ์„ธ์…˜์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์–ด ์•ฑ๊ณผ ์‚ฌํŒŒ๋ฆฌ ๊ฐ„ ์›ํ™œํ•œ ๋กœ๊ทธ์ธ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋ณด์•ˆ ์ธก๋ฉด์—์„œ SFSafariViewController๋ณด๋‹ค ๋” ๊ฐœ์„ ๋˜์—ˆ์œผ๋ฉฐ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰๋˜๋Š” ์•ฑ๊ณผ ์ฟ ๊ธฐ ๋“ฑ ๋ฐ์ดํ„ฐ ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

 

์ด ์ค‘์—์„œ๋„ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” WKWebView๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ„๋‹จํ•œ ์›น๋ทฐ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 


 

WKWebView๋Š” WebKit ๊ธฐ๋ฐ˜์˜ ์›น๋ทฐ์ด๊ธฐ ๋•Œ๋ฌธ์—

์ด๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋จผ์ € WebKit์„ ํ”„๋กœ์ ํŠธ์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


ํ”„๋กœ์ ํŠธ ์„ค์ • ํŒŒ์ผ์—์„œ Build Phases > Link Binary With Libraries๋กœ ์ด๋™ํ•ด +๋ฅผ ๋ˆŒ๋Ÿฌ WebKit.framework๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

 


๋จผ์ € ์Šคํ† ๋ฆฌ๋ณด๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

 


ViewController๋Š” Navigation Controller์™€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๊ณ ,

๊ฒ€์ƒ‰์–ด ์ž…๋ ฅ์„ ์œ„ํ•ด ์Šคํƒ๋ทฐ๋กœ ๊ฐ์‹ผ TextField, Button์„ ๋ฐฐ์น˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

ViewController์™€ WebViewController ๋ชจ๋‘ ์Šคํ† ๋ฆฌ๋ณด๋“œ์™€ ์ปดํฌ๋„ŒํŠธ ์—ฐ๊ฒฐ๋งŒ ํ•ด๋‘” ์ƒํƒœ์ž…๋‹ˆ๋‹ค.

 


 

ViewController.swift

tappedSearch Action ํ•จ์ˆ˜์—๋Š” ์ž…๋ ฅํ•œ ๊ฒ€์ƒ‰์–ด์™€ ํ•จ๊ป˜ WebViewController๋กœ ์ด๋™ํ•˜๋Š” ๋™์ž‘์„ ๊ตฌํ˜„ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var tvSearch: UITextField!/** ๊ฒ€์ƒ‰์–ด ํ…์ŠคํŠธํ•„๋“œ */
    
    /** life cycle */
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }

    @IBAction func tappedSearch(_ sender: Any) {

    }
}

 

 

๋จผ์ € ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•œ ๋’ค ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์›น๋ทฐ๋กœ ์ด๋™ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
ViewController์˜ tappedSearch ํ•จ์ˆ˜์— ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

let text: String = tvSearch.text!

 

text ๋ณ€์ˆ˜์— ์ž…๋ ฅ๋ฐ›์€ ๊ฒ€์ƒ‰์–ด๋ฅผ ๋„ฃ์–ด, WebViewController๋กœ ์ „๋‹ฌํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

 

 

์ด์–ด์„œ NavigationController์„ ์‚ฌ์šฉํ•˜์—ฌ WebViewController๋กœ ์ด๋™ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

if let navigationController = self.navigationController {
            
     if !(navigationController.topViewController?.description.contains("WebViewController"))! {
          let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
          let viewController = storyBoard.instantiateViewController(withIdentifier: "WebViewController") as! WebViewController
                
          viewController.search = text
          viewController.url = "https://m.search.naver.com/search.naver?sm=mtp_hty.top&where=m&"
                
          navigationController.pushViewController(viewController, animated: true)
     }
}

 

 

 

๊ฒ€์ƒ‰์–ด์™€ url์€ WebViewController์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

viewController.search = text
viewController.url = "https://m.search.naver.com/search.naver?sm=mtp_hty.top&where=m&"


๋„ค์ด๋ฒ„์— ํŠน์ • ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•ด ๊ฒ€์ƒ‰ํ•˜๋ฉด url์ด `https://m.search.naver.com/search.naver?sm=mtp_hty.top&where=m&query=๊ฒ€์ƒ‰์–ด` ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.
์œ„์™€ ๊ฐ™์ด query๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋„ค์ด๋ฒ„์˜ ๊ฒฐ๊ณผ ํ™”๋ฉด์„ ๋„์›Œ์ค„ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

 


 

WebViewController.swift

๋จผ์ € WebKit๋ฅผ import ํ•˜๊ณ , ์›น๋ทฐ๋ฅผ ๋‹ด์„ ํ”„๋กœํผํ‹ฐ๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

import UIKit
import WebKit

class WebViewController: UIViewController {

    @IBOutlet weak var webViewGroup: UIView!/** ๋ฐฐ๊ฒฝ ๋ทฐ */
    
    private var webView: WKWebView!/** ์›น๋ทฐ */
    
    var search: String!/** ๊ฒ€์ƒ‰์–ด */
    var url: String!/** url */
    
    
    /** life cycle */
    override func viewDidLoad() {
        super.viewDidLoad()
        
        /** ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ฐ” ํƒ€์ดํ‹€ */
        self.navigationItem.title = search
    }
}


์ด webView๋ฅผ ํ†ตํ•ด ์›น๋ทฐ๋ฅผ ๊ทธ๋ฆฌ๊ณ , ๋ฏธ๋ฆฌ ๊ทธ๋ ค๋‘” ๋ทฐ์ธ webViewGroup์— ์ถ”๊ฐ€ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

search, url ํ”„๋กœํผํ‹ฐ์—๋Š” ViewController๋กœ ๋ถ€ํ„ฐ ๊ฐ’์„ ์ „๋‹ฌ๋ฐ›์€ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

 


๋จผ์ € Delegate๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

webView.uiDelegate = self
webView.navigationDelegate = self
extension WebViewController: WKNavigationDelegate {
    
    public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    
print("\(navigationAction.request.url?.absoluteString ?? "")" )
        
        decisionHandler(.allow)
    }
}

extension WebViewController: WKUIDelegate {

    public func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        
    }
}

extension WebViewController: WKScriptMessageHandler {
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        
        print(message.name)
    }
}


decidePolicyFor ํ•จ์ˆ˜๋Š” ์œ ํšจํ•œ ๋„๋ฉ”์ธ์ธ์ง€ ์ฒดํฌํ•ฉ๋‹ˆ๋‹ค.

์•ž์„œ add()ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ๋ฉ”์‹œ์ง€๋ฅผ ๋“ฑ๋กํ–ˆ๋‹ค๋ฉด, WKScriptMessageHandler ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด javaScript(์ฆ‰, ์›น ํŽ˜์ด์ง€)๋กœ ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

์ด์–ด์„œ WebView ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

 

viewDidLoad()์— ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

WKPreferences๋Š” ์›น ๋ทฐ์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ์†์„ฑ์„ ์บก์Аํ™”ํ•œ ํด๋ž˜์Šค๋กœ, java๋‚˜ javaScript ์„ค์ •์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

let preferences = WKPreferences()
/** javaScript ์‚ฌ์šฉ ์„ค์ • */
preferences.javaScriptEnabled = true
/** ์ž๋™์œผ๋กœ javaScript๋ฅผ ํ†ตํ•ด ์ƒˆ ์ฐฝ ์—ด๊ธฐ ์„ค์ • */
preferences.javaScriptCanOpenWindowsAutomatically = true

 

 

 

WKUserContentController๋Š” ์›น๋ทฐ์™€ javaScript ๊ฐ„์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ด€๋ฆฌํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
javaScript์—์„œ ์•ฑ์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•  ๋•Œ๋Š” add() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ๋ฉ”์‹œ์ง€์˜ ์ด๋ฆ„์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

let contentController = WKUserContentController()
/** ์‚ฌ์šฉํ•  ๋ฉ”์‹œ์ง€ ๋“ฑ๋ก */
contentController.add(self, name: "bridge")

 

 

 

WKWebViewConfiguration๋Š” ์›น๋ทฐ๊ฐ€ ๋งจ ์ฒ˜์Œ ์ดˆ๊ธฐํ™”๋  ๋•Œ ํ˜ธ์ถœ๋˜๋ฉฐ, ์›น๋ทฐ๊ฐ€ ์ƒ์„ฑ๋œ ์ดํ›„์—๋Š” ์ด ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์†์„ฑ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด ์†์„ฑ์„ ์‚ฌ์šฉํ•ด WebView ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

let configuration = WKWebViewConfiguration()
/** preference, contentController ์„ค์ • */
configuration.preferences = preferences
configuration.userContentController = contentController

webView = WKWebView(frame: self.view.bounds, configuration: configuration)

 


๋‹ค์Œ๊ณผ ๊ฐ™์ด URLQueryItem() ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น๋ทฐ์— ๋‚˜ํƒ€๋‚ผ url์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

var components = URLComponents(string: url)!
components.queryItems = [ URLQueryItem(name: "query", value: search) ]

 

 

๋งˆ์ง€๋ง‰์œผ๋กœ ์ƒ์„ฑํ•œ webView๋ฅผ ์ ์šฉํ•œ ํ›„, requset ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์›น ํŽ˜์ด์ง€๋ฅผ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.

webViewGroup.addSubview(webView)
setAutoLayout(from: webView, to: webViewGroup)

let request = URLRequest(url: components.url!)
webView.load(request)

 

 

 

AutoLayout์€ ๋”ฐ๋กœ ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•ด ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

/** auto leyout ์„ค์ • */
public func setAutoLayout(from: UIView, to: UIView) {
        
from.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.init(item: from, attribute: .leading, relatedBy: .equal, toItem: to, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true
    NSLayoutConstraint.init(item: from, attribute: .trailing, relatedBy: .equal, toItem: to, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true
    NSLayoutConstraint.init(item: from, attribute: .top, relatedBy: .equal, toItem: to, attribute: .top, multiplier: 1.0, constant: 0).isActive = true
    NSLayoutConstraint.init(item: from, attribute: .bottom, relatedBy: .equal, toItem: to, attribute: .bottom, multiplier: 1.0, constant: 0).isActive = true
    view.layoutIfNeeded()
}

 

 

์•„๋ž˜๋Š” ๊ฒฐ๊ณผ ํ™”๋ฉด์ž…๋‹ˆ๋‹ค.

 

 

728x90


์ „์ฒด ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

ViewController.swift

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var tvSearch: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }

    /** ์›น ๋ทฐ๋กœ ์ด๋™ */
    @IBAction func tappedSearch(_ sender: Any) {
        let text: String = tvSearch.text!
        
        if let navigationController = self.navigationController {
            
            if !(navigationController.topViewController?.description.contains("WebViewController"))! {
                let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                let viewController = storyBoard.instantiateViewController(withIdentifier: "WebViewController") as! WebViewController
                
                viewController.search = text
                viewController.url = "https://m.search.naver.com/search.naver?sm=mtp_hty.top&where=m&"
                
                navigationController.pushViewController(viewController, animated: true)
            }
        }
    }
}

 


WebViewController.swift

import UIKit
import WebKit

class WebViewController: UIViewController {

    @IBOutlet weak var webViewGroup: UIView!/** ๋ฐฐ๊ฒฝ ๋ทฐ */
    
    private var webView: WKWebView!/** ์›น ๋ทฐ */
    
    var search: String!/** ๊ฒ€์ƒ‰์–ด */
    var url: String!/** url */
    
    
    /** life cycle */
    override func viewDidLoad() {
        super.viewDidLoad()
        
        /** ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ฐ” ํƒ€์ดํ‹€ */
        self.navigationItem.title = search
        
        let preferences = WKPreferences()
        preferences.javaScriptEnabled = true
        preferences.javaScriptCanOpenWindowsAutomatically = true
        
        let contentController = WKUserContentController()
        contentController.add(self, name: "bridge")
        
        let configuration = WKWebViewConfiguration()
        configuration.preferences = preferences
        configuration.userContentController = contentController
        
        webView = WKWebView(frame: self.view.bounds, configuration: configuration)
        
        var components = URLComponents(string: url)!
        components.queryItems = [ URLQueryItem(name: "query", value: search) ]
        
        let request = URLRequest(url: components.url!)
        
        webView.uiDelegate = self
        webView.navigationDelegate = self
        webViewGroup.addSubview(webView)
        setAutoLayout(from: webView, to: webViewGroup)
        webView.load(request)
        
        webView.alpha = 0
        UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseIn, animations: {
            self.webView.alpha = 1
        }) { _ in
            
        }
    }
    
    /** auto leyout ์„ค์ • */
    public func setAutoLayout(from: UIView, to: UIView) {
        
        from.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.init(item: from, attribute: .leading, relatedBy: .equal, toItem: to, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true
        NSLayoutConstraint.init(item: from, attribute: .trailing, relatedBy: .equal, toItem: to, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true
        NSLayoutConstraint.init(item: from, attribute: .top, relatedBy: .equal, toItem: to, attribute: .top, multiplier: 1.0, constant: 0).isActive = true
        NSLayoutConstraint.init(item: from, attribute: .bottom, relatedBy: .equal, toItem: to, attribute: .bottom, multiplier: 1.0, constant: 0).isActive = true
        view.layoutIfNeeded()
    }

}

extension WebViewController: WKNavigationDelegate {
    
    public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        
        print("\(navigationAction.request.url?.absoluteString ?? "")" )
        
        decisionHandler(.allow)
    }
}

extension WebViewController: WKUIDelegate {
    
    public func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        
    }
}

extension WebViewController: WKScriptMessageHandler {
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        
        print(message.name)
    }
}

 


 

์•„๋ž˜ ๋งํฌ์—์„œ๋„ ์ „์ฒด ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

https://github.com/hoojeong-dev/Toy-Project-iOS/tree/main/WebView

 

Toy-Project-iOS/WebView at main · hoojeong-dev/Toy-Project-iOS

Contribute to hoojeong-dev/Toy-Project-iOS development by creating an account on GitHub.

github.com

 

 

 

 

728x90

'๐Ÿ’ป Programming > iOS' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[iOS] Request Methods๋ฅผ ๊ณ๋“ค์ธ Alamofire ๊ฐ„๋‹จ ์‚ฌ์šฉ๋ฒ•  (0) 2025.02.27