每次如何将数据从最新的 ViewController 传递到 SwiftUI View ?
问题: 所以实际上我可以传递数据,但是我对数据的更新有疑问。
我想在我的SwiftUI项目中与UIKit接口,该项目需要使用后置摄像头来创建拾色器。 存储Color的变量每次在ViewController中更新时,但是当我想通过ViewControllerWrapper将其数据传递到ContentView中时,在我关闭并重新打开我的应用程序时,变量的值就是update。
我的实际工作:
内容视图:
struct ContentView: View {
@State var color: UIColor = UIColor.clear
var body: some View {
ZStack{
Color("c2").edgesIgnoringSafeArea(.all)
NavigationView{
VStack{
CameraView(color: $color)
DockView(color: $color)
}
.navigationViewStyle(StackNavigationViewStyle())
.navigationBarTitle("", displayMode: .inline)
.navigationBarItems(trailing: Image(systemName: "circle.grid.hex").font(.system(size: 28)).foregroundColor(Color("c1")))
}
}
}
}
(CameraView)视图控制器:
struct CameraView: View {
@Binding var color: UIColor
var body: some View {
ViewControllerWrapper(color: $color)
}
}
struct ViewControllerWrapper: UIViewControllerRepresentable {
typealias UIViewControllerType = ViewController
@Binding var color: UIColor
func makeUIViewController(context: UIViewControllerRepresentableContext<ViewControllerWrapper>) -> ViewController {
let v = ViewController()
return v
}
func updateUIViewController(_ uiViewController: ViewController, context: UIViewControllerRepresentableContext<ViewControllerWrapper>) {
color = uiViewController.color
}
}
class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
let captureSession = AVCaptureSession()
var currentDevice: AVCaptureDevice?
var center: CGPoint = CGPoint(x: WIDTH/2-4, y:WIDTH/2-4)
var color: UIColor = UIColor.clear
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
return
}
CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: CVOptionFlags(0)))
guard let baseAddr = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0) else {
return
}
let width = CVPixelBufferGetWidthOfPlane(imageBuffer, 0)
let height = CVPixelBufferGetHeightOfPlane(imageBuffer, 0)
let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, 0)
let colorSpace = CGColorSpaceCreateDeviceRGB()
let bimapInfo: CGBitmapInfo = [
.byteOrder32Little,
CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue)]
guard let content = CGContext(data: baseAddr, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bimapInfo.rawValue) else {
return
}
guard let cgImage = content.makeImage() else {
return
}
DispatchQueue.main.async {
self.previewLayer.contents = cgImage
self.color = self.previewLayer.pickColor(at: self.center)!
self.previewLayer.frame = self.view.frame
self.lineShape.strokeColor = self.color.cgColor
self.lineShape2.fillColor = self.color.cgColor
self.label.text = "#\(self.hexFromUIColor(color: self.color))"
}
}
let previewLayer = CALayer()
let lineShape = CAShapeLayer()
let lineShape1 = CAShapeLayer()
let lineShape2 = CAShapeLayer()
let lineShape3 = CAShapeLayer()
let label = UILabel()
func setupUI() {
previewLayer.frame = view.frame
previewLayer.contentsGravity = CALayerContentsGravity.resizeAspectFill
previewLayer.masksToBounds = true
previewLayer.setAffineTransform(CGAffineTransform(rotationAngle: CGFloat(.pi / 2.0)))
view.layer.insertSublayer(previewLayer, at: 0)
//Cercle
let linePath = UIBezierPath.init(ovalIn: CGRect.init(x: 0, y: 0, width: 40, height: 40))
lineShape.frame = CGRect.init(x: WIDTH/2-20, y:WIDTH/2-20, width: 40, height: 40)
lineShape.lineWidth = 5
lineShape.strokeColor = UIColor.red.cgColor
lineShape.path = linePath.cgPath
lineShape.fillColor = UIColor.clear.cgColor
self.view.layer.insertSublayer(lineShape, at: 1)
//Point
let linePath1 = UIBezierPath.init(ovalIn: CGRect.init(x: 0, y: 0, width: 8, height: 8))
lineShape1.frame = CGRect.init(x: WIDTH/2-4, y:WIDTH/2-4, width: 8, height: 8)
lineShape1.path = linePath1.cgPath
lineShape1.fillColor = UIColor.init(white: 0.7, alpha: 0.5).cgColor
self.view.layer.insertSublayer(lineShape1, at: 1)
//Preview
let linePath2 = UIBezierPath.init(ovalIn: CGRect.init(x: 0, y: 0, width: 25, height: 25))
lineShape2.frame = CGRect.init(x: WIDTH/2-70, y:120, width: 25, height: 25)
lineShape2.path = linePath2.cgPath
lineShape2.fillColor = UIColor.clear.cgColor
self.view.layer.insertSublayer(lineShape2, at: 1)
//Container
let linePath3 = UIBezierPath.init(roundedRect: CGRect.init(x: 0, y: 0, width: 150, height: 50), cornerRadius: 25)
lineShape3.frame = CGRect.init(x: WIDTH/2-80, y:107, width: 150, height: 30)
lineShape3.path = linePath3.cgPath
lineShape3.fillColor = UIColor(named: "c3")?.cgColor
self.view.layer.insertSublayer(lineShape3, at: 1)
//Label
label.frame = CGRect.init(x: WIDTH/2-35, y:120, width: 100, height: 21)
label.font = UIFont.systemFont(ofSize: 20, weight: UIFont.Weight.semibold)
label.tintColor = UIColor(named: "c1")
self.view.addSubview(label)
}
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
self.CreateUI()
}
let queue = DispatchQueue(label: "com.camera.video.queue")
func CreateUI(){
self.captureSession.sessionPreset = AVCaptureSession.Preset.hd1920x1080
self.currentDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)
do {
let captureDeviceInput = try AVCaptureDeviceInput(device: currentDevice!)
let videoOutput = AVCaptureVideoDataOutput()
videoOutput.videoSettings = ([kCVPixelBufferPixelFormatTypeKey as AnyHashable: NSNumber(value: kCMPixelFormat_32BGRA)] as! [String : Any])
videoOutput.alwaysDiscardsLateVideoFrames = true
videoOutput.setSampleBufferDelegate(self, queue: queue)
if self.captureSession.canAddOutput(videoOutput) {
self.captureSession.addOutput(videoOutput)
}
self.captureSession.addInput(captureDeviceInput)
} catch {
print(error)
return
}
self.captureSession.startRunning()
}
func hexFromUIColor(color: UIColor) -> String{
let hexString = String(format: "%02X%02X%02X",
Int(color.cgColor.components![0]*255.0),
Int(color.cgColor.components![1]*255.0),
Int(color.cgColor.components![2]*255.0))
return hexString
}
}
如果您知道如何在我的ContentView中获取数据的价值。
谢谢。