AVSampleBufferDisplayLayer в SwiftUI в UIViewRepresentable

#ios #swiftui #uiimageview

#iOS #swiftui #uiimageview

Вопрос:

Я хочу добавить AVSampleBufferDisplayLayer в top, если мой UIImageView, но мне нужен доступ к этому AVSampleBufferDisplayLayer в качестве свойства. Отображается ошибка, которая не является неизменяемой.


 struct CamerImageSUIView: UIViewRepresentable {
    
    internal lazy var cameraAVLayer: AVSampleBufferDisplayLayer = {
        let avLayer = AVSampleBufferDisplayLayer()
        avLayer.videoGravity = .resizeAspectFill
        return avLayer
    }()

    func makeUIView(context: Context)  -> ImageLoaderView {
        let imageView = ImageLoaderView()
        imageView.ribbonMode = false
        imageView.event = false
        imageView.tintColor = UIColor(named: "ColorC5")
        imageView.backgroundColor = UIColor(named: "ColorC3")
        imageView.contentMode = .scaleToFill

        //HERE IS THE PROBLEM BECAUSE cameraAVLayer is immutable
        imageView.layer.insertSublayer(cameraAVLayer, at: 0)
        cameraAVLayer.frame = imageView.layer.bounds

        return imageView
    }

    func updateUIView(_ uiView: ImageLoaderView, context: Context) {}
    
    
}

  

Ответ №1:

У меня была аналогичная проблема с моим приложением, и я придумал следующую реализацию.

  1. Создан объект модели, который имеет свойство displayLayer.
 class CameraImageState: ObservableObject {
    let displayLayer = AVSampleBufferDisplayLayer()
}
  
  1. Когда я создаю представление, я даю ссылку на этот объект модели (или свойство displayLayer)
 struct CamerImageSUIView: UIViewRepresentable {
    @ObservedObject var state: CameraImageState
    
    func makeUIView(context: Context)  -> ImageLoaderView {
        let imageView = ImageLoaderView()
        imageView.ribbonMode = false
        imageView.event = false
        imageView.tintColor = UIColor(named: "ColorC5")
        imageView.backgroundColor = UIColor(named: "ColorC3")
        imageView.contentMode = .scaleToFill

        state.displayLayer.videoGravity = .resizeAspectFill
        state.displayLayer.frame = imageView.layer.bounds
        imageView.layer.insertSublayer(state.displayLayer, at: 0)

        return imageView
    }

    func updateUIView(_ uiView: ImageLoaderView, context: Context) {}
}
  

Кстати, (хотя я не изменял ваш код) не имеет смысла устанавливать фрейм displayLayer в makeUIView, потому что он все равно изменится позже. Вам нужно сделать это в layoutsubviews() ImageLoaderView.