user3650307
user3650307

Reputation: 31

How to persist Cookies in WKWebview iOS Swift - iOS 13 SwiftUI

I am looking for solution for iOS 13 SDK WKWebview based app built with SwiftUI in order to make cookies saved between different sessions of app usage.

This problem has been numerously discussed acrossed stackoverflow provided with different soltuions for ObjectiveC and Swift with Storyboards.

I am asking the community if there is ready to use code examlpe of how to provide WKWebView Cookie Persistency on iOS 13 WKWebView app with SwiftUI used

To make it clear: my app accesses remote web server with web site designed to be like mobile app. It's not local web app with need to manipulate cookies locally. Simply to make cookies manipulation in web site from remote server in Jquery JS code of the page in order to work and be saved across different sessions of app,

My current version of code:

import SwiftUI
import WebKit

struct ContentView: View {
  var body: some View {
    WebView().edgesIgnoringSafeArea(.all)
  }
}

struct WebView: UIViewRepresentable {
  func makeUIView(context: Context) -> WKWebView {
    let webView = WKWebView()
    webView.scrollView.isScrollEnabled = false
    return webView
  }

  func updateUIView(_ webView: WKWebView, context: Context) {
    let liveView = "https://example.com/projectname/index.html"
    if let url = URL(string: liveView) {
       let request = URLRequest(url: url)
       webView.load(request)
    }
  }
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}
#endif

Upvotes: 3

Views: 5648

Answers (2)

Reth
Reth

Reputation: 67

You can use below approach to fetch all the cookies and inject desired ones back. Ideally get cookies from a secured page after logging in and save it in UserDefaults. Then inject the same when the app starts again:

struct WebView: UIViewRepresentable {
let url: URL
let cookies: [HTTPCookie]
@ObservedObject var webViewManager: WebViewManager

func makeCoordinator() -> Coordinator {
        return Coordinator(self)
    }

func makeUIView(context: Context) -> WKWebView {
    let webView = WKWebView()
    webView.load(URLRequest(url: url))
    webViewManager.webView = webView // Set the webView reference in the manager
    webView.navigationDelegate = context.coordinator
    return webView
}

func updateUIView(_ uiView: WKWebView, context: Context) {
    // Update the view if needed
    
}
class Coordinator: NSObject, WKNavigationDelegate {
    var parent: WebView
    
    init(_ parent: WebView) {
        self.parent = parent
    }
    
    // Called when the web view begins to receive data from the server
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        print(webView.url as Any)
        // If the URL is the login URL where the session token is obtained
        if let url = webView.url, url.absoluteString == "https://my-url.com/path/" {
            // Get session token from cookies after page redirects to desired url, say landing page
            
            webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in
                for cookie in cookies {
                    if cookie.name == "session_token" {
                        // Save session token to UserDefaults
                        print(cookie.value)
                        UserDefaults.standard.set(cookie.value, forKey: "SessionToken")
                    }
                }
            }
        }
    }
}
func setCookies() {
    webViewManager.setCookies(cookies)
}
}

class WebViewManager: ObservableObject {
  var webView: WKWebView?

func setCookies(_ cookies: [HTTPCookie]) {
    guard let webView = webView else { return }
    let cookieStore =webView.configuration.websiteDataStore.httpCookieStore
    cookies.forEach { cookieStore.setCookie($0) }
    
    // Reload the web view after setting cookies
    webView.reload()
  }
}

struct ContentView: View {
  @StateObject private var webViewHelper = WebViewHelper()
  @ObservedObject var webViewManager = WebViewManager() // observe the manager

  var body: some View {
      WebView(url: webViewHelper.url, cookies: webViewHelper.cookies, webViewManager: webViewManager) // pass the observed manager
        .onAppear {
            webViewManager.setCookies(webViewHelper.cookies)
        }
}
}
class WebViewHelper: ObservableObject {
  let url = URL(string: "https://my-url.com/path/")!
  let cookies: [HTTPCookie] = [
    HTTPCookie(properties: [
        .domain: "my-url.com",
        .path: "/",
        .name: "session_token",
        .value: UserDefaults.standard.string(forKey: "SessionToken") as Any
    ])!
]
}

Upvotes: 0

Jake
Jake

Reputation: 2216

Set the configuration webView.configuration.websiteDataStore.httpCookieStore

see this answer for an example

Upvotes: 1

Related Questions