How to delete WKWebview cookies
Asked Answered
S

14

43

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.

Stidham answered 8/7, 2015 at 10:22 Comment(0)
S
62

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];
Stidham answered 4/8, 2015 at 7:57 Comment(6)
using this approach only returns the domain level, i.e. facebook.com , it tells me there are cookies inside it. but i cannot delete or retrieve individual items. For example a session cookie inside facebook. The old approach would flatten all cookies into a single list. Is this by design or am i missing something. No information ive been able to find. - @pankajDemo
Have you tried removing record of type WKWebsiteDataTypeSessionStorage?Stidham
Sadly its being used as cookie, debugging in safari shows i have two domains being stored with an amount of other items being used cookies, local storage etc. And under HTTPCookieStore you see a flat list across all domains a list of cookies. This session cookie i want is in there. But not when requesting througuh tis new DataStore. I do however see the Two domain items. so its as through i need to drill down a second level.Demo
@PankajGaikar Is there a way to delete specific cookies from a domain?Oringa
@Oringa Sorry for delayed reply. I have not specifically done that, but I believe you can do it by searching the cookie with name.Stidham
Note that the WebKit API must be called on the main thread, unlike NSHTTPCookieStorage. If you're clearing cookies in a background thread you'll need to stick to NSHTTPCookieStorage.Tumbledown
S
24

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);
            })
        }
    }
}
Songster answered 18/4, 2017 at 12:30 Comment(0)
S
23

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()
    }
Stonework answered 7/2, 2019 at 12:29 Comment(0)
Z
6

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)
Zenda answered 27/6, 2016 at 23:9 Comment(1)
With this storage you're using a "private mode" where localStorage and others won't be available so your JavaScript may fail, but yes, it wipes everythingLigetti
S
5

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");
}];
Stilbite answered 20/11, 2015 at 4:53 Comment(0)
P
3

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]) { }
    }
}
Promethean answered 1/7, 2020 at 23:47 Comment(0)
C
2

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)
}
Cockswain answered 23/8, 2018 at 9:26 Comment(0)
H
2

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:{})
Hypoxanthine answered 14/6, 2021 at 6:47 Comment(0)
D
1

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

Darees answered 8/7, 2015 at 18:3 Comment(2)
Well, i'm afraid but this isn't working too.. I read somewhere that I have to delete local library's from device too, i'll be trying that too.Stidham
If you use WKProcessPool trick ( from #33157067 ) to share cookies between multiple WKWebViews, you need to create a new WKProcessPool too like in the answer.Ulland
A
0

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. :)

Antediluvian answered 8/7, 2015 at 10:29 Comment(3)
It doesn't really make sense, your code and mine one are same, Though I tried this code too. Nope, This one too not working for me.Stidham
OK no problem i will wait for your answerAntediluvian
For now, i am clueless, and have no idea what's happening here, still will try some workaround..Stidham
S
0

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()
Scotch answered 10/6, 2016 at 5:5 Comment(0)
E
0

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..

Ethbin answered 1/9, 2016 at 7:3 Comment(0)
P
0

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********

Parasang answered 27/1, 2020 at 4:22 Comment(0)
H
-6

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()
Hypocycloid answered 20/12, 2015 at 0:42 Comment(1)
This always returned an error for me. I passed true for the last parameter in NSSearchPathForDirectoriesInDomains and it worksBragi

© 2022 - 2024 — McMap. All rights reserved.