如何在 SwiftUI 中设置 addObserver?
How to set addObserver in SwiftUI?
如何在 SwiftUI 中添加 NotificationCenter.default.addObserve?
当我尝试添加观察者时出现以下错误
Argument of '#selector' refers to instance method 'VPNDidChangeStatus'
that is not exposed to Objective-C
但是当我在 func 前面添加 @objc 时,出现以下错误
@objc can only be used with members of classes, @objc protocols, and
concrete extensions of classes
这是我的代码
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)
}
交换这个
self.NC.addObserver(self, selector: #selector(self.VPNDidChangeStatus),
name: .NEVPNStatusDidChange, object: nil)
到
self.NC.addObserver(self, selector: #selector(VPNDidChangeStatus(_:)),
name: .NEVPNStatusDidChange, object: nil)
它不是 SwiftUI 原生方法,它是声明式和反应式的。相反,您应该使用 Combine 中的 NSNotificationCenter.publisher(for:object:)。
这对我有用
let NC = NotificationCenter.default
self.NC.addObserver(forName: .NEVPNStatusDidChange, object: nil, queue: nil,
using: self.VPNDidChangeStatus)
func VPNDidChangeStatus(_ notification: Notification) {
}
接受的答案可能有效,但实际上并不是您应该如何执行此操作。在 SwiftUI 中,您不需要以这种方式添加观察者。
你添加了一个发布者,它仍然可以监听从应用程序的非 SwiftUI 部分触发的 NSNotification 事件,而不需要合并。
举个例子,列表会在出现时更新,当它收到通知时,来自另一个视图/控制器或类似内容的已完成网络请求等。
如果出于某种原因需要触发 @objc 函数,则需要使用 UIViewControllerRepresentable
创建一个 Coordinator
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
}
}
我有一种 NotificationCenter
在 SwiftUI
中使用的方法。
通知扩展n
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"])
}
}
}
我使用这个扩展程序,所以它在呼叫站点上更好一些:
/// Extension
extension View {
func onReceive(_ name: Notification.Name,
center: NotificationCenter = .default,
object: AnyObject? = nil,
perform action: @escaping (Notification) -> Void) -> some View {
self.onReceive(
center.publisher(for: name, object: object), perform: action
)
}
}
/// Usage
struct MyView: View {
var body: some View {
Color.orange
.onReceive(.myNotification) { _ in
print(#function)
}
}
}
extension Notification.Name {
static let myNotification = Notification.Name("myNotification")
}
如何在 SwiftUI 中添加 NotificationCenter.default.addObserve?
当我尝试添加观察者时出现以下错误
Argument of '#selector' refers to instance method 'VPNDidChangeStatus' that is not exposed to Objective-C
但是当我在 func 前面添加 @objc 时,出现以下错误
@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes
这是我的代码
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)
}
交换这个
self.NC.addObserver(self, selector: #selector(self.VPNDidChangeStatus),
name: .NEVPNStatusDidChange, object: nil)
到
self.NC.addObserver(self, selector: #selector(VPNDidChangeStatus(_:)),
name: .NEVPNStatusDidChange, object: nil)
它不是 SwiftUI 原生方法,它是声明式和反应式的。相反,您应该使用 Combine 中的 NSNotificationCenter.publisher(for:object:)。
这对我有用
let NC = NotificationCenter.default
self.NC.addObserver(forName: .NEVPNStatusDidChange, object: nil, queue: nil,
using: self.VPNDidChangeStatus)
func VPNDidChangeStatus(_ notification: Notification) {
}
接受的答案可能有效,但实际上并不是您应该如何执行此操作。在 SwiftUI 中,您不需要以这种方式添加观察者。
你添加了一个发布者,它仍然可以监听从应用程序的非 SwiftUI 部分触发的 NSNotification 事件,而不需要合并。
举个例子,列表会在出现时更新,当它收到通知时,来自另一个视图/控制器或类似内容的已完成网络请求等。
如果出于某种原因需要触发 @objc 函数,则需要使用 UIViewControllerRepresentable
Coordinator
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
}
}
我有一种 NotificationCenter
在 SwiftUI
中使用的方法。
通知扩展n
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"])
}
}
}
我使用这个扩展程序,所以它在呼叫站点上更好一些:
/// Extension
extension View {
func onReceive(_ name: Notification.Name,
center: NotificationCenter = .default,
object: AnyObject? = nil,
perform action: @escaping (Notification) -> Void) -> some View {
self.onReceive(
center.publisher(for: name, object: object), perform: action
)
}
}
/// Usage
struct MyView: View {
var body: some View {
Color.orange
.onReceive(.myNotification) { _ in
print(#function)
}
}
}
extension Notification.Name {
static let myNotification = Notification.Name("myNotification")
}