为何LoginDateMonitorView会在调试器中产生大量日志信息?
问题原因分析:LoginDateMonitorView触发大量调试日志
核心问题
调试器中反复出现的[SwiftUI] 不允许在视图更新过程中发布变更,这将导致未定义行为日志,根源在于你对ObservableObject的objectWillChange实现不符合SwiftUI的规范要求。
具体触发原因
objectWillChange类型不匹配ObservableObject协议要求objectWillChange发送的是Void类型的信号(用于告知SwiftUI对象即将变更),但你在PropertyObserver扩展中返回的是AnyPublisher<Value, Never>,也就是直接发送了属性的具体值,而非符合要求的空信号。循环更新闭环
当User的lastLogin变化时,自定义发布者发送Date值触发视图更新,但视图更新过程中又会意外触发发布者再次发送信号,形成循环触发,最终导致数百条警告日志输出。
修复方案
修改PropertyObserver扩展中的objectWillChange实现,将属性值信号转换为符合要求的Void信号:
extension PropertyObserver { var objectWillChange: AnyPublisher<Void, Never> { object.publisher(for: property) .map { _ in () } // 将属性值转换为空信号 .eraseToAnyPublisher() } }
如果需要更严谨的内存管理(避免内存泄漏),可以结合关联对象存储订阅:
extension PropertyObserver { var objectWillChange: ObservableObjectPublisher { let publisher = ObservableObjectPublisher() object.publisher(for: property) .sink { _ in publisher.send() } .store(in: &cancellables) return publisher } private var cancellables: Set<AnyCancellable> { get { (objc_getAssociatedObject(self, &cancellablesKey) as? Set<AnyCancellable>) ?? .init() } set { objc_setAssociatedObject(self, &cancellablesKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } } private var cancellablesKey = 0
补充说明
ObservableObject的objectWillChange本质是一个"通知开关",只需要告诉SwiftUI「对象要变了,准备更新视图」即可,不需要传递具体的属性值。原实现的信号类型错误,打乱了SwiftUI的更新逻辑,从而触发了循环警告。
内容的提问来源于stack exchange,提问作者bobby123uk
相关产品推荐
相关产品推荐

