0

I need to plant a notification for using the notification center, which I started planting my observer in my class initialization, which I am not sure it is a correct place, but some time if we made a mistake in coding and we created more than one observer how we can solve the issue?

For creating this issue I made a button for that to making multiple observers, so now if I press on the button a new observer is going created and making same work more than once.

import SwiftUI

struct ContentView: View {
    
    @StateObject var myScreen: MyScreen = MyScreen.shared
    
    var body: some View {
        
        Button("plantNotificationObserver") {
            myScreen.plantNotificationObserver()
        }
        
        if let size: CGSize = myScreen.visibleFrame?.size {
            Text("visibleFrame size: " + String(describing: size))
                .animation(.default, value: size)
        }
        
    }
}






class MyScreen: ObservableObject {
    
    static let shared: MyScreen = MyScreen()
    
    init() {
        plantNotificationObserver()
    }
    
    @Published var visibleFrame: NSRect? = NSScreen.main?.visibleFrame
    
    func plantNotificationObserver() {
        
        NotificationCenter.default.addObserver(forName: NSApplication.didChangeScreenParametersNotification, object: NSApplication.shared, queue: .main) { notification in
            
            print("screen parameters changed")
            self.visibleFrame = NSScreen.main?.visibleFrame
            
        }
        
    }
    
}

Is there a way to list all my alive observers and killing the duplicated ones? I want have a bird view over my observers and correcting them in case if I made a mistake and created more than what I wanted?

1 Answers1

2

No, there is no way to query NotificationCenter for observers. It is up to you to keep your observation additions and removals balanced. You definitely should not try to post-hoc "fix" bad observations. Instead you need to follow patterns that make the code correct.

In this case, adding an observation with a button is very likely wrong. Your original idea of creating observations in init is generally the correct approach. This is much easier to balance, particularly if you use the selector: form of addObserver, since that form automatically cleans itself up. If you want to use the block form (as you have here), you need to keep the returned value in an ivar, and make sure to clean it up in deinit.

That said, as a debugging tool, you could swizzle NotificationCenter to replace the addObserver and removeObserver methods to keep track of things. I have done this myself to track down particularly difficult issues. But it is not a replacement for establishing balanced patterns in your code. You cannot avoid that.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610