Pankaj Gaikar
Pankaj Gaikar

Reputation: 2493

How to delete WKWebview cookies

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

Answers (14)

Pankaj Gaikar
Pankaj Gaikar

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

Alexander Volkov
Alexander Volkov

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

Jayesh Elamgodil
Jayesh Elamgodil

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

tikamchandrakar
tikamchandrakar

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

Shubham Mishra
Shubham Mishra

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

Sergi Gracia
Sergi Gracia

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

Simon Epskamp
Simon Epskamp

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

Jeba Moses
Jeba Moses

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

Zack Shapiro
Zack Shapiro

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

ykonda
ykonda

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

Esqarrouth
Esqarrouth

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

Kingiol
Kingiol

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

Subbu
Subbu

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

Rohit suvagiya
Rohit suvagiya

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

Related Questions