首页 > 解决方案 > 将数据从模型传递到 SwiftUI 中的视图

问题描述

public class CameraService: NSObject, AVCaptureFileOutputRecordingDelegate {
     
  @Published public var videoClips = [AVPlayerItem]()

  public func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
    let video: AVPlayerItem = AVPlayerItem(url:outputFileURL)
    videoClips.append(video)
  }
}

final class CameraModel: ObservableObject {
    
  private let service = CameraService()
  var videoClips: [AVPlayerItem]

  init() {   
    videoClips = service.videoClips
  }
}

struct CameraView: View {
    
  @StateObject var model = CameraModel()

  var body: some View {
    Button("video") {
      print(model.videoClips.count)
    }
  }
}

标签: iosswiftswiftui

解决方案


在当前的形式中,model.videoClips.count永远只会是 0,因为你设置videoClipsinit()它,然后它就再也不会更新了。

我猜你假设它会被更新,因为它CameraService.videoClips是一个@Published属性。但是,@Published只会被Views 和他们ObservableObject的 s 自动观看。所以,这里有两个问题:a)CameraService不是aObservableObject也不CameraModel是 a View

我的第一个建议是CameraModel彻底放弃。也许这是一个尝试做一个最小示例的功能,但在当前的形式下,它什么也没做——它只是一个没有功能的中间人。所以,CameraService变成一个ObservableObject,这意味着该@Published属性可以工作,你会很高兴。

关于导航到另一个屏幕,这可能是一个单独的问题的最佳选择,但我会在这里留下一个简短的答案:

//in your view
NavigationLink(destination: DetailView(videoClips: service.videoClips)) {
  Text("Link")
} 

(这是假设你已经变成CameraService了你的ObservableObject

如果由于某种原因您确实需要CameraModeland CameraService,您可以通过执行以下操作来连接两者:

class CameraModel : ObservableObject {
    private let service = CameraService()
    @Published var videoClips : [AVPlayerItem] = [] //note that this is @Published now
        
    init() {
        service.$videoClips.assign(to: &self.$videoClips) //use a Combine Publisher to get updates from the CameraService videoClips and assign them to this class's videoClips any time there's an update 
    }
}

推荐阅读