【问题标题】:@Published UIImage property not updating in SwiftUI@Published UIImage 属性未在 SwiftUI 中更新
【发布时间】:2022-01-04 07:49:18
【问题描述】:

我想在 UIImageView 中显示 MJPEG 流。

我已经实现了流加载并通过委托将图像发送到 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!)")
    } 
}

委托函数按预期使用每个新图像调用,我将其分配给@Published var cameraImage。

在视图端,@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
  • 很酷。也许我仍然需要了解其中的区别。但是我在其他具有@Published 属性(如文本(字符串))的视图模型中使用@ObservedObject 具有相同的模式。但他们工作正常。那么有什么区别呢?
  • 谢谢。你能发表你的评论作为答案,所以我可以标记它,拜托。

标签: swiftui uiimageview urlsession mjpeg


【解决方案1】:

CameraView 中替换

@ObservedObject var cameraViewModel 

@StateObject var cameraViewModel

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-12
    • 2020-10-21
    • 2021-09-07
    • 2021-10-14
    • 2020-04-30
    • 2021-03-23
    • 2020-12-27
    • 1970-01-01
    相关资源
    最近更新 更多