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

如何让SwiftUI数组同步Objective-C类中NSMutableArray的动态变化

问题根因

你当前写法的核心问题是:NSArray as! [PcapCppPacketWrappper] 这个操作是值拷贝,Swift的Array是值类型,你初始化时只是把当前ObjC的NSMutableArray里的元素拷贝了一份存到本地packets变量里,之后ObjC侧的NSMutableArray变更完全不会同步到Swift侧的这个packets变量。

可行解决方案

方案1:用Combine框架做同步(推荐)

  • 第一步:在Swift侧创建可观察对象,用来同步ObjC侧的数组内容
import Combine
class PacketObserver: ObservableObject {
    @Published var packets: [PcapCppPacketWrappper] = []
    private var device: PcapCppDevWrapper
    
    init(device: PcapCppDevWrapper) {
        self.device = device
    }
    
    // 供ObjC侧新增包时主动调用,或者你也可以加个Timer定时轮询同步
    @objc func syncPackets() {
        let newPackets = device.getPacketArray() as! [PcapCppPacketWrappper]
        // 仅在内容有变化时更新,避免无用渲染
        if newPackets.count != packets.count {
            DispatchQueue.main.async {
                self.packets = newPackets
            }
        }
    }
}
  • 第二步:修改SwiftUI视图的代码,使用可观察对象渲染内容
struct CaptureView: View {
    @StateObject private var packetObserver: PacketObserver
    @Binding var captureWindowIsOpen: Bool
    
    init(device: PcapCppDevWrapper, captureWindowIsOpen: Binding<Bool>) {
        self._packetObserver = StateObject(wrappedValue: PacketObserver(device: device))
        self._captureWindowIsOpen = captureWindowIsOpen
    }
    
    var body: some View {
        ScrollView {
            LazyVStack(alignment: .leading) {
                ForEach(packetObserver.packets, id: \.self) { packet in
                    // 此处替换为你自己的单条数据包渲染逻辑
                    Text(packet.description)
                }
            }
        }
    }
}
  • 第三步(性能最优):修改ObjC侧的PcapCppDevWrapper代码,每次往NSMutableArray中添加完数据包之后,调用Swift侧PacketObserver的syncPackets方法触发同步即可,不需要定时轮询。

方案2:KVO监听同步

如果不想加Combine依赖,也可以用KVO实现:

  • 修改ObjC侧PcapCppDevWrapper的代码,给数组属性增加KVO触发逻辑:
// .h文件声明
@interface PcapCppDevWrapper : NSObject
@property (nonatomic, strong, readonly) NSMutableArray *packetArray;
@end

// .m文件插入数据包的位置增加KVO通知
[self willChangeValueForKey:@"packetArray"];
[_packetArray addObject:newPacket];
[self didChangeValueForKey:@"packetArray"];
  • 在Swift侧直接监听packetArray属性的变化,更新本地数组即可。
注意事项
  • 后台线程新增包之后,所有更新SwiftUI视图的操作必须切换到主线程执行,否则会出现渲染异常甚至崩溃
  • 如果数据包量非常大,建议做增量更新,不要每次都全量替换数组,避免UI卡顿

内容的提问来源于stack exchange,提问作者publicstaticmain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 04:24:04