Cookies Sharing between wkwebviews
Try the following code in your loadView() for both of your ViewController classes:
webConfiguration.processPool = viewHome.processPool
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webConfiguration.processPool = viewHome.processPool
webViewHome = WKWebView(frame: .zero, configuration: webConfiguration)
Additional:For standard, please Use the camel case in the Class name convention (viewHome -> ViewHome).
Cookie sharing between multiple WKWebViews
Got this working by using the same WKProcessPool for all the webviews.
First create a process pool once somewhere:
processPool = [[WKProcessPool alloc] init];
Then use it when creating WKWebviews. The pool must be set in the init method, not afterwards.
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.processPool = processPool;
webview = [[WKWebView alloc] initWithFrame:frame configuration:config];
WKWebViews (multiple) - sharing cookies, localStorage in Swift
I think it is best if you use SFSafariViewController
for your needs.
As the documentation states:
In iOS 9 and 10, it shares cookies and other website data with Safari.
It means, that it is going to use the same cookies and data from the Safari browser, which is even better. If I am not mistaken, the user can be logged in through Safari, and when he comes to your app, he will not have to log in again.
Here is the full documentation for it:
SFSafariViewController
Update:
If you still want to do what you already started, according to this answer here in Objective-C, this is the solution in Swift:
You need a place where you would store the persistent 'process pool'. In your case, it is
YourModelObject
singleton
class YourModelObject {
static let sharedInstance = YourModelObject()
let processPool = WKProcessPool()
}
Use the shared
processPool
before initializing the webView. This is the initialization function which you would call in theloadView()
for every viewController:
override func loadView() {
super.loadView() //don't forget this line
setupWebView()
}
private func setupWebView() {
let config = WKWebViewConfiguration()
config.processPool = YourModelObject.sharedInstance.processPool
self.webView = WKWebView(frame: .zero, configuration: config)
self.webView.navigationDelegate = self
self.webView.scrollView.delegate = self
self.view = self.webView
}
Getting all cookies from WKWebView
Finally, httpCookieStore
for WKWebsiteDataStore
landed in iOS 11.
https://developer.apple.com/documentation/webkit/wkwebsitedatastore?changes=latest_minor
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.
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...).
Use shared WKWebViewCookies for a request
1) If your cookies are not HTTP-only, you can get them by evaluating JavaScript command document.cookie
on webView
and use them for your request.
If they are HTTP-only, it seems that there is no working method to do this.
There is no documented way to sync cookies between WKWebView
and NSURLSession
as far as I know.
2) Another approach (if cookies belong to same domain which REST API belongs) - create "background" webView
with same process pool and perform all operations to REST API via this instance - cookies will be added automatically (even HTTP-only):
You can set any params (method/body/headers/etc) to request and load
it vialoadRequest:
; If your REST API returns JSON, you can use JavaScript commanddocument.body
to get it;Getting response code a little bit harder - you need to implement
webView:decidePolicyForNavigationResponse:
method ofWKNavigationDelegate
and catch
it.Also, you need to keep in mind that you can perform only 1 request
inwebView
simultaneously. So, you may need to create some queue
of requests that will be performed one after another.
Related Topics
Sending an Email from Your App with an Image Attached in Swift
Swift Safely Unwrapping Optinal Strings and Ints
Rename Default Rendered Headings Like "Example" in Swift Markup Language
Swift: Hashable Struct with Dictionary Property
How to Create a Nsmutabledictionary in Swift
Avplayer Can't Resume After Paused + Some Waiting
Implementing Reconnection with Urlsession Publisher and Combine
Synchronized Realm - Airplane Mode
What Is Existentialmetatype in Swift
How to Play Avplayeritems Immediately
How to Make a Button Draggable/Movable with Swiftui
How to Make Sfspeechrecognizer Available on MACos
Consuming a Soap Web Service with Swift
How to Add an Admob Gadbannerview to Every View