You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中ObservedObject无法获取点击事件的问题排查

问题:ObservedObject无法响应点击事件更新UI

点击AdsView中的图片后,尝试修改network.networkObserver.sucess状态,但主ContentView的Text无法同步更新,相关代码如下:

ContentView 代码

struct ContentView: View {
    
    @StateObject var network = Network()
    
    var body: some View {
        VStack {
            SecondView(network: network)
            Text(self.network.networkObserver.sucess?.description ?? "Nil")
            
        }
    }      
}

AdsView(即SecondView)代码

public struct AdsView: View {
    
    @State private var banner: Model?
    @State private var image: UIImage?
    @State private var scale: Double = 1.0
    
    @ObservedObject var network: Network
    
 public var body: some View {
        Group {
            if let image = image {
                Text("AdSDK mockup. Click on image")
                
                Image(uiImage: image)
                    .resizable()
                    .scaledToFit()
                    .scaleEffect(scale)
                    .gesture (
                        TapGesture()
                            .onEnded { _ in
                                self.scale -= 0.1
                                network.networkObserver.sucess = network.networkObserver.sucess ?? false ? false : true
                            }
                        )
            } else {
                Rectangle()
                    .background(Color.red)
            }
        }
    }
}

Network 类代码(自定义库中)

public class Network: ObservableObject {
    
    @Published public var adImage: UIImage?
    @Published public var networkObserver = NetworkObserver()
    
    public init() { }

    public func getImage(for imageURL: String) async throws { }
}

NetworkObserver 类代码

public class NetworkObserver {
    
    public var sucess: Bool?
    public var error: RequestError?
    
    public init() { }
}

错误原因分析

  1. NetworkObserver未实现可观察机制:sucess属性无@Published标记,属性变化无法触发SwiftUI视图更新。
  2. 引用类型属性更新未触发通知:Network类中networkObserver虽标记@Published,但它是class类型(引用类型),修改内部sucess属性时,networkObserver自身引用未改变,因此@Published不会发送更新通知。
  3. 三目运算符语法歧义:network.networkObserver.sucess ?? false ? false : true优先级混乱,逻辑不符合预期,需添加括号明确执行顺序。

解决方案

方案一:让NetworkObserver成为可观察对象(推荐)

修改NetworkObserver类,使其遵循ObservableObject并标记内部属性为@Published:

public class NetworkObserver: ObservableObject {
    @Published public var sucess: Bool?
    @Published public var error: RequestError?
    
    public init() { }
}

调整Network类,移除networkObserver的@Published标记(自身已是ObservableObject,内部属性变化会自动发通知):

public class Network: ObservableObject {
    
    @Published public var adImage: UIImage?
    public var networkObserver = NetworkObserver() // 去掉@Published
    
    public init() { }

    public func getImage(for imageURL: String) async throws { }
}

修正AdsView中的逻辑,简化状态切换代码:

TapGesture()
    .onEnded { _ in
        self.scale -= 0.1
        // 简化sucess状态切换逻辑
        network.networkObserver.sucess = !(network.networkObserver.sucess ?? false)
    }

方案二:手动发送更新通知(备选)

若无法修改NetworkObserver结构,可在修改sucess后手动触发Network的更新通知:

TapGesture()
    .onEnded { _ in
        self.scale -= 0.1
        // 手动发送更新通知
        network.objectWillChange.send()
        // 修正三目运算符优先级
        network.networkObserver.sucess = (network.networkObserver.sucess ?? false) ? false : true
    }

内容的提问来源于stack exchange,提问作者V D Purohit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 08:06:51