微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何让 Picker 使用 ForEach 循环返回 VideoFormat var?

如何解决如何让 Picker 使用 ForEach 循环返回 VideoFormat var?

我正在尝试使用选择器通过 ForEach 循环从 Twilio 的视频 API 中选择 VideoFormat。循环正在运行——它列出了所有格式正确的格式字符串。

这是我的观点,SettingsView

import SwiftUI

struct SettingsView: View {
    
    @EnvironmentObject var twilioState: TwilioState
        
    var body: some View {
        Form {
            Section(header: Text("Stream")) {
                HStack {
                    Text("Device")
                    Spacer()
                    Text("\(twilioState.captureDevice?.localizedname ?? "N/A")")
                }

这就是我遇到麻烦的地方。我似乎无法让 Picker 为我的 selection$twilioState.videoFormat 赋值。我怀疑这与 idVideoFormat 不符合 Hashable 有关系?我正在考虑将 selection 更改为 Int 并使用 ForEach 的范围,例如 0..<twilioState.videoFormats.count

                Picker("Select a Format",selection: $twilioState.videoFormat) {
                    if let videoFormats = twilioState.videoFormats {
                        ForEach(videoFormats,id: \.self) {
                            Text("\(twilioState.getVideoFormatString(videoFormat: $0))")
                                .tag($0)
                        }
                    }
                }
                .disabled(twilioState.videoFormats == nil)

其余的是 twilioState.videoFormat 的列表,因为我试图弄清楚如何成功实现 Picker

                HStack {
                    Text("Format")
                    Spacer()
                    if let videoFormat = twilioState.videoFormat {
                        Text("\(twilioState.getVideoFormatString(videoFormat: videoFormat))")
                    } else {
                        Text("N/A")
                    }
                }
            }
        }
        .navigationBarTitle("Settings")
    }
}

这是我的状态模型,TwilioState

import Foundation
import TwilioVideo
import Combine


class TwilioState: ObservableObject {

    let twilioService = TwilioService()
    private var cancellables = Set<AnyCancellable>()
    var camera: CameraSource?
    
    @Published var videoFormat: VideoFormat?
    @Published var videoFormats: [VideoFormat]?
    @Published var captureDevice: AVCaptureDevice?
    @Published var twilioError: TwilioError?
        
    init() {
        
        twilioService.setCaptureDevice(captureDevice: self.captureDevice)
            .sink { completion in
                switch completion {
                case let .failure(twilioError):
                    return self.twilioError = twilioError
                case .finished:
                    return print("Capture device set")
                }
            } receiveValue: { captureDevice in
                self.captureDevice = captureDevice
            }
            .store(in: &cancellables)

        twilioService.getVideoFormats(captureDevice: self.captureDevice!)
            .sink { completion in
                switch completion {
                case let .failure(twilioError):
                    return self.twilioError = twilioError
                case .finished: return print("Capture device formats set")
                }
            } receiveValue: { videoFormats in
                self.videoFormats = videoFormats
            }
            .store(in: &cancellables)
    }
    
    func getVideoFormatString(videoFormat: VideoFormat) -> String {
        return "\(videoFormat.dimensions.width) x \(videoFormat.dimensions.height) @ \(videoFormat.frameRate)"
    }
    
    deinit {
        // We are done with camera
        if let camera = self.camera {
            camera.stopCapture()
            self.camera = nil
        }
    }
}

如果有帮助,这是服务函数 getVideoFormats(),它为我的模型 @Published videoFormats 中的 TwilioState 提供值:

    func getVideoFormats(captureDevice: AVCaptureDevice) -> AnyPublisher<[VideoFormat],TwilioError> {
        return Just(captureDevice)
            .map { captureDevice -> [VideoFormat] in
                return CameraSource.supportedFormats(captureDevice: captureDevice)
                    .compactMap { $0 as? VideoFormat }
            }
            .setFailureType(to: TwilioError.self)
            .erasetoAnyPublisher()
    }

解决方法

我通过使用标签修饰符将选择类型转换为可选类型来解决这个问题:

                Picker("Select a Format",selection: $twilioState.videoFormat) {
                    if let videoFormats = twilioState.videoFormats {
                        ForEach(videoFormats,id: \.self) { videoFormat in
                            Text("\(twilioState.getVideoFormatString(videoFormat: videoFormat))")
                                .tag(videoFormat as VideoFormat?)
                        }
                    }
                }

查看此帖子了解更多信息:Picker for optional data type in SwiftUI?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。