35

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.

Pankaj Gaikar
  • 1,619
  • 1
  • 18
  • 23

13 Answers13

55

Apple released new APIs for iOS 9, so now we can remove domain specific cookies stored for WKWebView with below code, but this will only work on devices with iOS version 9 or later:

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);
             }
         ];
       }
     }
   }
 ];

Above snippet will sure work for iOS 9 and later. Unfortunately if we use WKWebView for iOS versions before iOS 9, we still have to stick to 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];

Below is 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);
                })
            }
        }
    }

And Swift 4:

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
  )
}
Amaury Liet
  • 7,261
  • 1
  • 14
  • 21
Pankaj Gaikar
  • 1,619
  • 1
  • 18
  • 23
  • 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. - @pankaj – Woodmister1 Jun 30 '16 at 10:40
  • Have you tried removing record of type WKWebsiteDataTypeSessionStorage? – Pankaj Gaikar Jun 30 '16 at 12:40
  • 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. – Woodmister1 Jun 30 '16 at 13:42
  • @PankajGaikar Is there a way to delete specific cookies from a domain? – Crystal Mar 05 '19 at 16:27
  • @Crystal Sorry for delayed reply. I have not specifically done that, but I believe you can do it by searching the cookie with name. – Pankaj Gaikar Mar 25 '19 at 10:17
  • 1
    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. – IGx89 Jan 31 '21 at 20:34
22

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);
            })
        }
    }
}
Simon Epskamp
  • 6,866
  • 2
  • 45
  • 49
13

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()
    }
Shubham Mishra
  • 1,107
  • 10
  • 24
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");
}];
Kingiol
  • 1,137
  • 9
  • 8
5

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)
Zack Shapiro
  • 5,202
  • 14
  • 65
  • 121
  • 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 everything – Salavert Mar 19 '19 at 08:18
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

Subbu
  • 2,068
  • 11
  • 18
  • 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. – Pankaj Gaikar Jul 09 '15 at 08:39
  • If you use WKProcessPool trick ( from http://stackoverflow.com/questions/33156567/getting-all-cookies-from-wkwebview/33198799#33198799 ) to share cookies between multiple WKWebViews, you need to create a new WKProcessPool too like in the answer. – Peacemoon Jan 04 '17 at 10:41
1

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)
}
Sergi Gracia
  • 280
  • 1
  • 6
1

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]) { }
    }
}
Jayesh Elamgodil
  • 1,427
  • 11
  • 15
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. :)

Rohit suvagiya
  • 1,001
  • 2
  • 12
  • 40
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()
ykonda
  • 352
  • 4
  • 13
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..

Jeba Moses
  • 641
  • 5
  • 21
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********

-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()
Esqarrouth
  • 35,175
  • 17
  • 147
  • 154
  • This always returned an error for me. I passed `true` for the last parameter in `NSSearchPathForDirectoriesInDomains` and it works – funct7 Sep 24 '16 at 19:13