Reputation: 2493
For now I am doing like this
NSHTTPCookie *cookie;
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [storage cookies])
{
[storage deleteCookie:cookie];
}
But it is not working on iOS 8, 64-bit device.
Any other way the clean cookies of WKWebview? Any help will be appreciated. thanks.
Upvotes: 43
Views: 52334
Reputation: 2493
Apple released new APIs for iOS 9 and newer versions, so now we can remove domain-specific cookies stored for WKWebView with the below code.
Swift 4/5 version:
let dataStore = WKWebsiteDataStore.default()
dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { records in
dataStore.removeData(
ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(),
for: records.filter { $0.displayName.contains("facebook") },
completionHandler: completion
)
}
Below is the Swift 3 version
let dataStore = WKWebsiteDataStore.default()
dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { (records) in
for record in records {
if record.displayName.contains("facebook") {
dataStore.removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), for: [record], completionHandler: {
print("Deleted: " + record.displayName);
})
}
}
}
Objective-C version -
WKWebsiteDataStore *dateStore = [WKWebsiteDataStore defaultDataStore];
[dateStore
fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes]
completionHandler:^(NSArray<WKWebsiteDataRecord *> * __nonnull records) {
for (WKWebsiteDataRecord *record in records) {
if ( [record.displayName containsString:@"facebook"]) {
[[WKWebsiteDataStore defaultDataStore]
removeDataOfTypes:record.dataTypes
forDataRecords:@[record]
completionHandler:^{
NSLog(@"Cookies for %@ deleted successfully",record.displayName);
}
];
}
}
}
];
The above snippet will surely work for iOS 9 and later. Unfortunately, if we use WKWebView for iOS versions before iOS 9, we still have to stick to the traditional method and delete the whole cookies storage as below.
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *cookiesFolderPath = [libraryPath stringByAppendingString:@"/Cookies"];
NSError *errors;
[[NSFileManager defaultManager] removeItemAtPath:cookiesFolderPath error:&errors];
Upvotes: 62
Reputation: 8407
Swift 5
/// old API cookies
for cookie in HTTPCookieStorage.shared.cookies ?? [] {
HTTPCookieStorage.shared.deleteCookie(cookie)
}
/// URL cache
URLCache.shared.removeAllCachedResponses()
/// WebKit cache
let date = Date(timeIntervalSince1970: 0)
WKWebsiteDataStore.default().removeData(
ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(),
modifiedSince: date,
completionHandler:{})
Upvotes: 2
Reputation: 1477
Building on top of all the existing answers, if you are trying to clear cookies and data records for a specific WKWebView instance 'webView' and not the 'default' stored cookies and data records, you could use the following:
let dataStore = webView.configuration.websiteDataStore
let cookieStore = dataStore.httpCookieStore
cookieStore.getAllCookies {
$0.forEach { cookie in
cookieStore.delete(cookie)
}
}
dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { records in
records.forEach { record in
dataStore.removeData(ofTypes: record.dataTypes, for: [record]) { }
}
}
Upvotes: 3
Reputation: 92
In WKWebView having issue to write and read its taking some time , So when you fetch the cookie some time you will get updated cookie but sometime it will be old one, and you will get error on any server request. I was facing this issue in 3 Days ,
Solution: No need to store cookies in WKWebsiteDataStore.
Getting cookies:
Swift:
extension WKWebView {
private var httpCookieStore: WKHTTPCookieStore { return WKWebsiteDataStore.default().httpCookieStore }
func getCookies(for domain: String? = nil, completion: @escaping ([String : Any])->()) {
var cookieDict = [String : AnyObject]()
httpCookieStore.getAllCookies { cookies in
for cookie in cookies {
if let domain = domain {
if cookie.domain.contains(domain) {
cookieDict[cookie.name] = cookie.properties as AnyObject?
}
} else {
cookieDict[cookie.name] = cookie.properties as AnyObject?
}
}
completion(cookieDict)
}
}
}
Objective-c :
-(void )getAllCookies
{
NSMutableString *updatedCockies= [[NSMutableString alloc] init];
if (@available(iOS 11.0, *)) {
WKHTTPCookieStore *cookieStore = _webView.configuration.websiteDataStore.httpCookieStore;
NSLog(@"cookieStore *********************: %@",cookieStore);
[cookieStore getAllCookies:^(NSArray* cookies) {
NSHTTPCookie *cookie;
for(cookie in cookies){
NSLog(@"%@",cookie)
}
self->updatedCookie = updatedCockies;
NSLog(@"cookie *********************: %@", self->updatedCookie);
}];
}
}
Every time you want new cookie so you need to write below code: Given Sharpio
Swift :
let config = WKWebViewConfiguration()
if #available(iOS 9.0, *) {
config.websiteDataStore = WKWebsiteDataStore.nonPersistentDataStore()
} else {
// I have no idea what to do for iOS 8 yet but this works in 9.
}
let webView = WKWebView(frame: .zero, configuration: config)
Objective C--
WKWebViewConfiguration *wkWebConfig = [WKWebViewConfiguration new];
wkWebConfig.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
self.webView = [[WKWebView alloc] initWithFrame: CGRectZero
configuration: wkWebConfig];
*******Every time you will get new cookies********
Upvotes: 0
Reputation: 1331
Supports iOS 11.0 and above
Following solution worked well for me:
Step 1. Remove Cookie from HTTPCookieStorage
Step 2. Fetch data records from WKWebsiteDataStore
and delete them.
Step 3. Create a new WKProcessPool
Create a WKWebView Extension:
extension WKWebView {
func cleanAllCookies() {
HTTPCookieStorage.shared.removeCookies(since: Date.distantPast)
print("All cookies deleted")
WKWebsiteDataStore.default().fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { records in
records.forEach { record in
WKWebsiteDataStore.default().removeData(ofTypes: record.dataTypes, for: [record], completionHandler: {})
print("Cookie ::: \(record) deleted")
}
}
}
func refreshCookies() {
self.configuration.processPool = WKProcessPool()
}
}
Usage:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
webView.cleanAllCookies()
webView.refreshCookies()
}
Upvotes: 23
Reputation: 288
Swift 4 and shorter version:
let dataStore = WKWebsiteDataStore.default()
dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { records in
dataStore.removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(),
for: records.filter { $0.displayName.contains("facebook") },
completionHandler: completion)
}
Upvotes: 2
Reputation: 10036
Swift 3 version of Sarat's answer:
let dataStore = WKWebsiteDataStore.default()
dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { (records) in
for record in records {
if record.displayName.contains("facebook") {
dataStore.removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), for: [record], completionHandler: {
print("Deleted: " + record.displayName);
})
}
}
}
Upvotes: 24
Reputation: 849
WKWebview storing nothing inside [NSHTTPCookieStorage sharedHTTPCookieStorage].
clearing WKWebsiteDataStore will be the solution for this problem.
Still for IOS8 which is using WKwebview, this method is not applicable..
Upvotes: 0
Reputation: 6998
None of these options worked for me but I found one that did:
let config = WKWebViewConfiguration()
if #available(iOS 9.0, *) {
config.websiteDataStore = WKWebsiteDataStore.nonPersistentDataStore()
} else {
// I have no idea what to do for iOS 8 yet but this works in 9.
}
let webView = WKWebView(frame: .zero, configuration: config)
Upvotes: 6
Reputation: 527
Esqarrouth's answer is only partially right.
The correct swift version is:
var libraryPath : String = NSFileManager().URLsForDirectory(.LibraryDirectory, inDomains: .UserDomainMask).first!.path!
libraryPath += "/Cookies"
do {
try NSFileManager.defaultManager().removeItemAtPath(libraryPath)
} catch {
print("error")
}
NSURLCache.sharedURLCache().removeAllCachedResponses()
Upvotes: 0
Reputation: 39201
Swift version:
var libraryPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.LibraryDirectory, NSSearchPathDomainMask.UserDomainMask, false).first!
libraryPath += "/Cookies"
do {
let result = try NSFileManager.defaultManager().removeItemAtPath(libraryPath)
print(result)
} catch {
print("error")
}
NSURLCache.sharedURLCache().removeAllCachedResponses()
Upvotes: -6
Reputation: 1155
In iOS9:
//// Optional data
NSSet *websiteDataTypes
= [NSSet setWithArray:@[
WKWebsiteDataTypeDiskCache,
//WKWebsiteDataTypeOfflineWebApplicationCache,
WKWebsiteDataTypeMemoryCache,
//WKWebsiteDataTypeLocalStorage,
//WKWebsiteDataTypeCookies,
//WKWebsiteDataTypeSessionStorage,
//WKWebsiteDataTypeIndexedDBDatabases,
//WKWebsiteDataTypeWebSQLDatabases
]];
//// All kinds of data
//NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes];
//// Date from
NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
//// Execute
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
// Done
NSLog(@"remove done");
}];
Upvotes: 5
Reputation: 2148
In addition to clearing cookies in the shared cookie storage, i'd try clearing the cache (NSURLCache) and discard the WKWebView and create a new one with a new WKProcessPool
Upvotes: 1
Reputation: 1015
It seems like NSHTTPCookieStorage is now being used in iOS 8.2 to correctly clear cookies, as required. I had shipped an app which would run this code prior to opening a WKWebView based login:
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [storage cookies])
{
[storage deleteCookie:cookie];
}
Where earlier than iOS 8.2 the website would auto-login using the saved cookies, it now correctly asks the user to re-login. All this happened without me shipping an update to the app. :)
Upvotes: 0