i have it like this:
import SwiftUI
import VisionKit
import Combine
import AVFoundation
import MessageUI
struct ScannerScreen: View {
@State private var isShowingScanner = false
@State private var scannedText = ""
@State private var codeProcessorMessages: [MessageModel] = []
private let mailComposeDelegate = MailDelegate()
var body: some View {
if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
ZStack(alignment: .top) {
ScannerView(scannedText: $scannedText, codeProcessorMessages: $codeProcessorMessages)
.ignoresSafeArea()
VStack {
ForEach(codeProcessorMessages, id: \.self) { message in
Text(message.text)
.padding()
.foregroundColor(.white)
.background(message.isGlutenFree ? Color.green : Color.red)
.cornerRadius(5)
}
.padding()
.padding(.bottom, 30)
}
VStack {
Spacer()
HStack {
Spacer()
Text(scannedText)
.padding()
.foregroundColor(.black)
.background(Color.white
.opacity(0.8)
.cornerRadius(10))
.opacity(scannedText.isEmpty ? 0 : 1)
Button(action: {
self.presentMailCompose()
}) {
Text("Nahlásit změnu")
.padding()
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(10)
.opacity(scannedText.isEmpty ? 0 : 1)
}
}
}
.padding()
}
.onChange(of: scannedText) { newText in
processCodeWithCodeProcessor(code: newText)
}
} else {
VStack {
Text("Přístup k fotoaparátu není povolen.")
Text("Povolte přístup v nastaveních zařízení.")
Button(action: {
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(url)
}
}) {
Text("Otevřít nastavení aplikace")
.foregroundColor(.greenField)
}
}
}
}
private func processCodeWithCodeProcessor(code: String) {
let processor = CodeProcessor()
codeProcessorMessages = processor.processCode(givenCode: code).map { message in
let isGlutenFree = message.contains("bezlepková")
return MessageModel(text: message, isGlutenFree: isGlutenFree)
}
}
}
struct ScannerScreen_Previews: PreviewProvider {
static var previews: some View {
ScannerScreen()
}
}
// Structure representing a message with gluten-free information
struct MessageModel: Hashable {
let text: String
let isGlutenFree: Bool
}
struct ScannerView: UIViewControllerRepresentable {
@Binding var scannedText: String
@Binding var codeProcessorMessages: [MessageModel]
func makeUIViewController(context: Context) -> ScannerViewController {
return ScannerViewController(scannedText: $scannedText, codeProcessorMessages: $codeProcessorMessages)
}
func updateUIViewController(_ uiViewController: ScannerViewController, context: Context) {}
}
class ScannerViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
@Binding var scannedText: String
@Binding var codeProcessorMessages: [MessageModel]
var captureSession: AVCaptureSession!
var previewLayer: AVCaptureVideoPreviewLayer!
init(scannedText: Binding<String>, codeProcessorMessages: Binding<[MessageModel]>) {
_scannedText = scannedText
_codeProcessorMessages = codeProcessorMessages
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
captureSession = AVCaptureSession()
let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .back)
guard let videoCaptureDevice = discoverySession.devices.first else { return }
let videoInput: AVCaptureDeviceInput
do {
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
} catch let error {
print(error)
return
}
if (captureSession.canAddInput(videoInput)) {
captureSession.addInput(videoInput)
} else {
print("Could not add video input")
return
}
let metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput)) {
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = [.ean8, .ean13, .pdf417]
} else {
print("Could not add metadata output")
return
}
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.frame = view.layer.bounds
previewLayer.videoGravity = .resizeAspectFill
view.layer.addSublayer(previewLayer)
// Start `AVCaptureSession` on a different thread
DispatchQueue.global().async {
self.captureSession.startRunning()
}
}
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
guard let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject else { return }
guard let stringValue = metadataObject.stringValue else { return }
scannedText = stringValue
}
}
extension ScannerScreen {
private class MailDelegate: NSObject, MFMailComposeViewControllerDelegate {
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
controller.dismiss(animated: true)
}
}
Topic:
Developer Tools & Services
SubTopic:
Xcode
Tags: