I have an app with several content blockers extension. Their configuration is fine and they act as they are supposed to.
However I need to call reloadContentBlocker(withIdentifier:completionHandler:)
from SFContentBlockerManager
when I've updated the filter lists for example.
Here is a code example (with NSLog for timestamp purposes below):
func reload(_ callback: @escaping((Bool) -> Void)) {
NSLog("Reload start")
let contentBlockersIdentifiers = ["com.aaa.bbb.ContentBlocker.ExampleA", "com.aaa.bbb.ContentBlocker.ExampleB", "com.aaa.bbb.ContentBlocker.ExampleC", "com.aaa.bbb.ContentBlocker.ExampleD", "com.aaa.bbb.ContentBlocker.ExampleE"]
var failures: [String] = [String]()
let dispatchSemaphore = DispatchSemaphore(value: 0)
let dispatchQueue = DispatchQueue(label: "reload-queue", qos: .userInitiated)
dispatchQueue.async {
NSLog("Reloading content blockers")
for aContentBlockerIdentifier in contentBlockersIdentifiers {
NSLog("Reloading '\(aContentBlockerIdentifier)'")
SFContentBlockerManager.reloadContentBlocker(withIdentifier: aContentBlockerIdentifier) { (error) in
if let error = error?.localizedDescription {
NSLog("Failed to reload '\(aContentBlockerIdentifier)': \(error)")
failures.append(aContentBlockerIdentifier)
} else {
NSLog("Successfully reloaded '\(aContentBlockerIdentifier)'")
}
dispatchSemaphore.signal()
}
dispatchSemaphore.wait()
}
callback(failures.isEmpty)
NSLog("Reload end")
}
}
This is what is prints:
16:41:43.391543+0200 Reload start
16:41:43.392003+0200 Reloading content blockers
16:41:43.392125+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleA'
16:41:50.010102+0200 Successfully reloaded 'com.aaa.bbb.ContentBlocker.ExampleA'
16:41:50.010299+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleB'
16:41:50.351554+0200 Failed to reload 'com.aaa.bbb.ContentBlocker.ExampleB': The operation couldn’t be completed. (WKErrorDomain error 2.)
16:41:50.351676+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleC'
16:41:50.493327+0200 Failed to reload 'com.aaa.bbb.ContentBlocker.ExampleC': The operation couldn’t be completed. (WKErrorDomain error 2.)
16:41:50.493429+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleD'
16:41:50.631578+0200 Failed to reload 'com.aaa.bbb.ContentBlocker.ExampleD': The operation couldn’t be completed. (WKErrorDomain error 2.)
16:41:50.631681+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleE'
16:41:50.718466+0200 Failed to reload 'com.aaa.bbb.ContentBlocker.ExampleE': The operation couldn’t be completed. (WKErrorDomain error 2.)
16:41:50.718600+0200 Reload end
It apparently tries to do the reload one content blocker after another (as I wanted to do with the DispatchSemaphore
). However after the first one succeeded the following are failures.
Now let's go and disable the Content Blockers in Setting App > Safari > Content Blockers and try again:
16:55:05.699392+0200 Reload start
16:55:05.700171+0200 Reloading content blockers
16:55:05.700564+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleA'
16:55:05.714444+0200 Successfully reloaded 'com.aaa.bbb.ContentBlocker.ExampleB'
16:55:05.714909+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleB'
16:55:05.723056+0200 Successfully reloaded 'com.aaa.bbb.ContentBlocker.ExampleB'
16:55:05.723343+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleC'
16:55:05.730565+0200 Successfully reloaded 'com.aaa.bbb.ContentBlocker.ExampleC'
16:55:05.730775+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleD'
16:55:05.735733+0200 Successfully reloaded 'com.aaa.bbb.ContentBlocker.ExampleD'
16:55:05.735841+0200 Reloading 'com.aaa.bbb.ContentBlocker.ExampleE'
16:55:05.740758+0200 Successfully reloaded 'com.aaa.bbb.ContentBlocker.ExampleE'
16:55:05.740865+0200 Reload end
Surprise... it works. But I would rather not ask my users to :
- go manually disable the Content Blockers in the Settings
- perform the update manually (while waiting to develop automatic refresh)
- go manually re-enable the Content Blockers in the Settings
I'm missing something somewhere (maybe a thread issue). Hopefully someone will be able to help!