swiftui - @Published UIImage 属性未在 SwiftUI 中更新

标签 swiftui uiimageview urlsession mjpeg

我想在 UIImageView 中显示 MJPEG 流。

我已经实现了流加载并通过委托(delegate)将图像发送到 CameraViewModel。

final class CameraViewModel: ObservableObject {
    
    lazy var cameraService = CameraService(delegate: self)
    
    @Published var cameraImage = UIImage(systemName: "cloud.heavyrain.fill")
    
    func play() {
        cameraService.play()
    }
    
    func stop() {
        cameraService.stop()
    }
}

extension CameraViewModel: CameraServiceDelegateProtocol {
    func frame(image: UIImage) {
        cameraImage = image
        print("updated image \(self.cameraImage!)")
    } 
}

按照预期,每个新图像都会调用委托(delegate)函数,并将其分配给@Published varcameraImage。

在 View 端,@Published 属性用于填充 UIImageView,但图像不会更新。


struct CameraView: View {
    @Binding var showCamera: Bool
    @ObservedObject var cameraViewModel: CameraViewModel = CameraViewModel()
    var body: some View {
        VStack {
            Image(uiImage: cameraViewModel.cameraImage!).aspectRatio(contentMode: .fit).frame(height: 200)
            
            Button("Close") {
                cameraViewModel.stop()
                showCamera.toggle()
            }.onAppear() {
                cameraViewModel.play()
            }
        }
    }
}

VStack 中的 Image(....) 没有更新,我似乎无法弄清楚出了什么问题。

作为引用,这里是 CameraService:

protocol CameraServiceDelegateProtocol {
    func frame(image: UIImage) -> Void
}

protocol CameraServiceProtocol {
    var rosServiceDelegate: CameraServiceDelegateProtocol { get set }
}

class CameraService: NSObject, ObservableObject {
    var cameraServiceDelegate: CameraServiceDelegateProtocol
    let realUrl = URL(string: "http://192.168.45.100:8080/stream?topic=/image_raw")
    var dataTask: URLSessionDataTask?
    var receivedData: NSMutableData = NSMutableData()
    var session: URLSession?
    
    init(delegate: CameraServiceDelegateProtocol) {
        cameraServiceDelegate = delegate
    }
    
    func play() {
        session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)
        dataTask = session?.dataTask(with: realUrl!)
        dataTask?.resume()
    }
    
    func stop() {
        dataTask?.cancel()
    }
}

extension CameraService: URLSessionDataDelegate {
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
        if self.receivedData.length > 0,
            let receivedImage = UIImage(data: self.receivedData as Data) {
                
            DispatchQueue.main.async {
                self.cameraServiceDelegate.frame(image: receivedImage)
            }
                
            self.receivedData = NSMutableData()
        }
            
        completionHandler(URLSession.ResponseDisposition.allow) //.Cancel,If you want to stop the download
            
    }
        
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        self.receivedData.append(data)
    }
}

最佳答案

CameraView中替换

@ObservedObject var cameraViewModel 

@StateObject var cameraViewModel

关于swiftui - @Published UIImage 属性未在 SwiftUI 中更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70121206/

相关文章:

uitableview - TableView 重新加载不适用于 SwiftUI 中的 UIViewRepresentable

ios - 如何在 SwiftUI 中为图像设置动画,以播放帧动画

ios - 我在 UIImageView 中添加图像但它不显示

Android:如何使用现有的图形元素

networking - 如何使用Combine框架和SwiftUI发布网络请求的数据

list - 如何为 SwiftUI 列表中的单个行设置动画?

ios - 列表内的 SwiftUI ScrollView 具有可怕的性能影响

php - uploadTask 方法不起作用 URLSession Swift 3

ios - 将 UIImage View 作为 subview 添加到 UIView 的实例

ios - 如何传递给循环调用的 URLSession.shared.dataTask?