I have a requirement to persist my cookies across application restarts.
Originally when using UIWebView
I was able to achieve this with an extension on UserDefaults
import Foundation
extension UserDefaults {
typealias CookieProperties = [HTTPCookiePropertyKey: Any]
private static let cookieKey = "app_cookie_jar"
func storeCookies() {
guard let cookies = HTTPCookieStorage.shared.cookies else { return }
let cookiePropertiesArray = cookies.compactMap { $0.properties }
set(cookiePropertiesArray, forKey: UserDefaults.cookieKey)
synchronize()
}
func fetchCookies() {
let cookiePropertiesArray = value(forKey: UserDefaults.cookieKey) as? [CookieProperties]
cookiePropertiesArray?.forEach {
if let cookie = HTTPCookie(properties: $0) {
HTTPCookieStorage.shared.setCookie(cookie)
}
}
}
}
I would then call this in various life cycle methods
func applicationWillEnterForeground() {
defaults.fetchCookies()
...
}
func applicationDidEnterBackground() {
defaults.storeCookies()
...
}
However now my application is using WKWebView
and I have the same requirement. I am currently sharing the cookie store between the different web views in my app by way of a shared singleton WKProcessPool
class ProcessPool {
static let shared = WKProcessPool()
}
However on a restart, some cookies are not persisted. Mainly cookies that do not have an exp
date and cannot be updated on the server to have one.
The extension above is using HTTPCookieStorage
however I need to achieve something of the same fashion (or better) using WKHTTPCookieStore
and am unsure how.
I was hoping to do something like this
func storeCookies() {
let __cookies = WKHTTPCookieStore()
__cookies.getAllCookies { cookies in
....
}
}
But I do not believe WKHTTPCookieStore
can be invoked in this way.
I am also very aware of the issues around sensitive data such as cookies in UserDefaults
, this is not a production app and long before release will have this functionality removed and replaced with a proper, secure solution. This is sadly just where we are with the product at this point in time.
You need to access WKWebsiteDataStore
first, this will give you access to the cookie store.
func storeCookies() {
let __cookies = WKWebsiteDataStore.default()
__cookies.httpCookieStore.getAllCookies { cookies in
print(cookies)
}
}