Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set addObserver in SwiftUI?

How do I add NotificationCenter.default.addObserve in SwiftUI?

When I tried adding observer I get below error

Argument of '#selector' refers to instance method 'VPNDidChangeStatus' that is not exposed to Objective-C

But when I add @objc in front of func I get below error

@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes

Here is my code

let NC = NotificationCenter.default  var body: some View {      VStack() {       }.onAppear {             self.NC.addObserver(self, selector: #selector(self.VPNDidChangeStatus),                               name: .NEVPNStatusDidChange, object: nil)       } }   @objc func VPNDidChangeStatus(_ notification: Notification) {     //    print("VPNDidChangeStatus", VPNManager.shared.status) } 
like image 984
O-mkar Avatar asked Nov 12 '19 11:11

O-mkar


2 Answers

The accepted answer may work but is not really how you're supposed to do this. In SwiftUI you don't need to add an observer in that way.

You add a publisher and it still can listen to NSNotification events triggered from non-SwiftUI parts of the app and without needing combine.

Here as an example, a list will update when it appears and when it receives a notification, from a completed network request on another view / controller or something similar etc.

If you need to then trigger an @objc func for some reason, you will need to create a Coordinator with UIViewControllerRepresentable

struct YourSwiftUIView: View {      let pub = NotificationCenter.default             .publisher(for: NSNotification.Name("YourNameHere"))       var body: some View {         List() {             ForEach(userData.viewModels) { viewModel in                 SomeRow(viewModel: viewModel)             }         }         .onAppear(perform: loadData)         .onReceive(pub) { (output) in             self.loadData()         }     }      func loadData() {         // do stuff     } } 
like image 86
MadeByDouglas Avatar answered Sep 21 '22 03:09

MadeByDouglas


I have one approach for NotificationCenter usage in SwiftUI.

For more information Apple Documentation

Notification extension

extension NSNotification {     static let ImageClick = Notification.Name.init("ImageClick") } 

ContentView

struct ContentView: View {     var body: some View {         VStack {             DetailView()         }         .onReceive(NotificationCenter.default.publisher(for: NSNotification.ImageClick))         { obj in            // Change key as per your "userInfo"             if let userInfo = obj.userInfo, let info = userInfo["info"] {               print(info)            }         }     } } 

DetailView

struct DetailView: View {     var body: some View {         Image(systemName: "wifi")             .frame(width: 30,height: 30, alignment: .center)             .foregroundColor(.black)             .onTapGesture {                 NotificationCenter.default.post(name: NSNotification.ImageClick,                                                  object: nil, userInfo: ["info": "Test"])         }     } } 
like image 33
Rohit Makwana Avatar answered Sep 20 '22 03:09

Rohit Makwana