WKWebView Persistent Storage of Cookies
This is actually a tough one because there's a) some bug that's still not solved by Apple (I think) and b) depends on what cookies you want, I think.
I wasn't able to test this now, but I can give you some pointers:
- Getting cookies from
NSHTTPCookieStorage.sharedHTTPCookieStorage()
. This one seems buggy, apparently the cookies aren't immediately saved forNSHTTPCookieStorage
to find them. People suggest to trigger a save by resetting the process pool, but I don't know whether that reliably works. You might want to try that out for yourself, though. - The process pool is not really what saves the cookies (though it defines whether they are shared as you correctly stated). The documentation says that's
WKWebsiteDataStore
, so I'd look that up. At least getting the cookies from there usingfetchDataRecordsOfTypes:completionHandler:
might be possible (not sure how to set them, though, and I assume you can't just save the store in user defaults for the same reason as for the process pool). - Should you manage to get the cookies you need (or rather their values), but not be able to restore them as I guess will be the case, look here (basically it shows how to simply prepare the httprequest with them already, relevant part:
[request addValue:@"TeskCookieKey1=TeskCookieValue1;TeskCookieKey2=TeskCookieValue2;" forHTTPHeaderField:@"Cookie"]
). - If all else fails, check this. I know providing just link only answers is not good, but I can't copy all that and just want to add it for completeness sake.
One last thing in general: I said that your success might also depend on the type of cookie. That's because this answer states that cookies set by the server are not accessible via NSHTTPCookieStorage
. I don't know whether that's relevant to you (but I guess it is, since you're probably looking for a session, i.e. server-set cookie, correct?) and I don't know whether this means that the other methods fail as well.
If all else fails, you might consider saving the users credentials somewhere (keychain, for example) and reuse them on the next app start to auth automatically. This might not restore all session data, but considering the user quit the app that's maybe actually desirable?
Also perhaps certain values can be caught and saved for later use using an injected script, like mentioned here (obviously not for setting them at start, but maybe retrieve them at some point. You need to know how the site works then, of course).
I hope that could at least point you towards some new directions solving the issue. It's not as trivial as it should be, it seems (then again, session cookies are kind of a security relevant thing, so maybe hiding them away from the App is a conscious design choice by Apple...).
Swift persistent cookie storage
To share all new cookies between multiple webviews you can use WKProcessPool
so just create the single pool for your app and set it to your webviews:
let ProcessPool = WKProcessPool()
...
let configuration = WKWebViewConfiguration()
configuration.processPool = ProcessPool
webView = WKWebView(frame: self.view.bounds, configuration: configuration)
If you want to be notified about changes with cookies you should add an observer to WKWebsiteDataStore
before creating your webviews:
WKWebsiteDataStore.default().httpCookieStore.add(self)
...
extension AppDelegate : WKHTTPCookieStoreObserver {
func cookiesDidChange(in cookieStore: WKHTTPCookieStore) {
cookieStore.getAllCookies { cookies in
print(cookies)
}
}
}
By default all cookies from webviews are stored between your app's launches.
Getting all cookies from WKWebView
Finally, httpCookieStore
for WKWebsiteDataStore
landed in iOS 11.
https://developer.apple.com/documentation/webkit/wkwebsitedatastore?changes=latest_minor
How can I persists cookies across app restarts with WKWebView / WKHTTPCookieStore
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)
}
}
Can I set the cookies to be used by a WKWebView?
Edit for iOS 11+ only
Use WKHTTPCookieStore:
let cookie = HTTPCookie(properties: [
.domain: "example.com",
.path: "/",
.name: "MyCookieName",
.value: "MyCookieValue",
.secure: "TRUE",
.expires: NSDate(timeIntervalSinceNow: 31556926)
])!
webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie)
Since you are pulling them over from HTTPCookeStorage, you can do this:
let cookies = HTTPCookieStorage.shared.cookies ?? []
for cookie in cookies {
webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie)
}
Old answer for iOS 10 and below
If you require your cookies to be set on the initial load request, you can set them on NSMutableURLRequest. Because cookies are just a specially formatted request header this can be achieved like so:
WKWebView * webView = /*set up your webView*/
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com/index.html"]];
[request addValue:@"TeskCookieKey1=TeskCookieValue1;TeskCookieKey2=TeskCookieValue2;" forHTTPHeaderField:@"Cookie"];
// use stringWithFormat: in the above line to inject your values programmatically
[webView loadRequest:request];
If you require subsequent AJAX requests on the page to have their cookies set, this can be achieved by simply using WKUserScript to set the values programmatically via javascript at document start like so:
WKUserContentController* userContentController = WKUserContentController.new;
WKUserScript * cookieScript = [[WKUserScript alloc]
initWithSource: @"document.cookie = 'TeskCookieKey1=TeskCookieValue1';document.cookie = 'TeskCookieKey2=TeskCookieValue2';"
injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
// again, use stringWithFormat: in the above line to inject your values programmatically
[userContentController addUserScript:cookieScript];
WKWebViewConfiguration* webViewConfig = WKWebViewConfiguration.new;
webViewConfig.userContentController = userContentController;
WKWebView * webView = [[WKWebView alloc] initWithFrame:CGRectMake(/*set your values*/) configuration:webViewConfig];
Combining these two techniques should give you enough tools to transfer cookie values from Native App Land to Web View Land. You can find more info on the cookie javascript API on Mozilla's page if you require some more advanced cookies.
Yeah, it sucks that Apple is not supporting many of the niceties of UIWebView. Not sure if they will ever support them, but hopefully they will get on this soon. Hope this helps!
Related Topics
Swift - Which Types to Use? Nsstring or String
Remove Grey Background on Link Clicked in iOS Safari/Chrome/Firefox
Fix CSS Hover on Iphone/Ipad/Ipod
How to Get the Udid in iOS 6 and iOS 7
Run Timer in 'Background' When App Is Closed
How to Save a Uicolor with Userdefaults
Differences Between Udid and Uuid
How to Set an Nsdate Object to Midnight
Alamofire Invalid Value Around Character 0
Perform Background Tasks When App Is Terminated
How to Give an "Identifier" to a View Controller Within My Storyboard
Change iPhone Uislider Bar Image
Adding Navigation Bar Programmatically iOS
How to Keep Uitableview Contentoffset After Calling -Reloaddata
How to Find Bluetooth Audio Devices in iOS
Instead of Push Segue How to Replace View Controller (Or Remove from Navigation Stack)