If you’re building an iOS app with webviews, you need to decide whether to use WKWebView or SFSafariViewController. The WebView version gives you a lot more control, but you can’t use Safari Extensions. On the other hand, the Safari version automatically gets some of the features of Safari like content blocking extensions, but customization options are pretty limited and it doesn’t support loading local HTML files.

In this demo, I’m going to walk through a simple Cookie Consent blocker in WKWebView using the Hush block list, a Swift library from the AdGuard team, and the WKContentRuleListStore class that was added way back in iOS 11.

First, download the Hush block list and add it to your project.

Next, load the file as a [String] that is split on newlines.

guard let path = Bundle.main.path(forResource: "cookiemonster", ofType: "txt") else {
    return "[{\"trigger\": {\"url-filter\": \".*\",\"if-domain\": [\"domain.com\"]},\"action\":{\"type\": \"ignore-previous-rules\"}}]"
}

let file = URL(filePath: path)
guard let rules = try? String(contentsOf: file).components(separatedBy: .newlines) else {
    return "[{\"trigger\": {\"url-filter\": \".*\",\"if-domain\": [\"domain.com\"]},\"action\":{\"type\": \"ignore-previous-rules\"}}]"
}

The fallback here is just a rule that doesn’t block anything.

After that, convert this list into something that WKContentRuleListStore can use with the AdGuard library.

let convertedRules = ContentBlockerConverter().convertArray(rules: rules).converted

And finally, compile the blocklist and add it to the WKWebView configuration.

WKContentRuleListStore.default().compileContentRuleList(
    forIdentifier: "ContentBlockingRules",
    encodedContentRuleList: convertedRules) { (contentRuleList, error) in

        if let _ = error {
            return
        }

        if let contentRuleList = contentRuleList {
            webview.configuration.userContentController.add(contentRuleList)
        }

        let request = URLRequest(url: url)
        webview.load(request)
}

And to prove it works, here is a before and after from Stack Overflow.