How to reload the Content Blocker Extenstion?

Hi,

I’m using the “Content Blocker Extension” in my project, and have been informed that I have to call SFContentBlockerManager.reloadContentBlockerWithIdentifier() in my main app to reload the data in blockerList.json.

But I don’t really know HOW I should call it. Any ideas?

Are you using SwiftUI or UIKit?

I am using SwiftUI. Do you know how to use SFContentBlockerManager.reloadContentBlockerWithIdentifier()?

Does this link help?

Sorry I haven’t worked with this myself

@mikaelacaron
So I looked at the link and it seems to address the same problem I have, but if I understand it correctly, he uses a function in AppDelegate. This is a problem for me since I don’t have an AppDelegate.

Do you know if there is a way around it?

You need to use SceneDelegate

willConnectTo function instead of didFinishLaunchingWithOptions

@mikaelacaron
Well, the thing is I don’t have SceneDelegate or AppDelegate. So I’m not sure what to do
If im not mistaken they were removed in one of the more recent updates

Ohhhh yes you’re using the new SwiftUI lifecycle

Here’s some more details about how it works

@mikaelacaron
I saw the video, which made me think, shouldn’t something like this work?

 Button(action: {
                SFContentBlockerManager.reloadContentBlocker(withIdentifier: contentBlockerId, completionHandler: nil)

            }) {
                Text("Reload ContentBlocker")
            }

I’ve never really done anything with Content Blockers, but…

If in UIKit you would call

SFContentBlockerManager.reloadContentBlocker(withIdentifier:completionHandler:)

in the app delegate’s applicationDidBecomeActive method, then when using SwiftUI, you should be able to call it by doing something like this:

struct MyContentBlockingApp: App {
    @Environment(\.scenePhase) var scenePhase
    
    //whatever else you gotta do here
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onChange(of: scenePhase) { newPhase in
                    switch newPhase {
                        case .active:
                            SFContentBlockerManager.reloadContentBlocker(withIdentifier: contentBlockerId, completionHandler: nil)
                        case .inactive:
                            //do whatever when your app becomes inactive
                        case .background:
                            //do whatever when your app goes into the background
                        @unknown default:
                            print("unknown phase")
                    }
                }
        }
    }
}

Or you could watch out for a notification, like so:

struct MyContentBlockingApp: App {
    //blah blah blah
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in
                    SFContentBlockerManager.reloadContentBlocker(withIdentifier: contentBlockerId, completionHandler: nil)
                }
        }
    }
}

You can also add an app delegate to a SwiftUI app: How to add an AppDelegate to a SwiftUI app

But, like I said, I’ve never really done anything with content blocking, so this may not work for your purposes. Worth a try, though.

@roosterboy
Thanks for the answer I will definitely check it out.
Even though you never really have done anything with content blocking, do you think I can simply call it in a button?
Like this

Button(action: {
SFContentBlockerManager.reloadContentBlocker(withIdentifier:completionHandler:)
   } {
         Text("Update")
      }

I tried doing it like this, but couldnt really get it to work
BTW: I’m using SwiftUI 2.0 life cycle

I… guess? I honestly have no clue.

I’m going to go with no.

The point of adding it to the app delegate is because you want this to initialize at the start of the app.

Create an init function in the file that has @main (Inside the struct)

And put it there

I dunno, calling it from the applicationDidBecomeActive method indicates that it can be called whenever the app moves from inactive state to active rather than just at init time. Which means, theoretically at least, that it could be called at other times as well. Say, when the user updates the content blocking rules and wants to apply those rules. Wouldn’t be very handy if you always had to quit and restart the app for changes to take effect.

Hmm, now I’m intrigued. I’ll have a go at playing around with this over the next couple of days. Should be interesting.

1 Like

Yes exactly, thats why I wanted to connect it to a button and not just call it when the app is active.
So I don’t know how or why but for some reason it works now. I basically just added a button in my main app where I call SFContentBlockerManager.reloadContentBlocker() and it seems to update the content blocker with the new data just fine.

I did the exact same thing a week ago and it didnt work, so im just waiting for it all to fail.

But it would be great if you would playing around with it and come back with some new insight

As far as I know content blocker only applies to Safari, but do you know if it is possible to do the same for Chrome? If so, how?