Slide 1

Slide 1 text

ָ͘͠؆୯ʹʂ 23ίʔυͷಡΈऔΓػೳΛ࣮૷͠Α͏ J04%$+BQBO

Slide 2

Slide 2 text

ࣗݾ঺հ ΃Μ͗Μ͞Μ !QFOHVJOTBO@QH ϑΣϯϦϧJ04ΤϯδχΞ ಘҙͳݴޠɿؔ੢ห ۤखͳݴޠɿஸೡͳ೔ຊޠ

Slide 3

Slide 3 text

એ఻ w ࠾༻ެࣜ-*/&࢝Ί·ͨ͠ʂ w εϙϯαʔϒʔε

Slide 4

Slide 4 text

͸͡Ίʹ w J04%$ͷτʔΫ͸Έͳ͞Μͱͷίϛϡχέʔγϣϯͷ৔ w ฉ͍͍ͯΔํ͸ϦΞΫγϣϯΛ͓ئ͍͠·͢ʂʂ w χίχίͷΈΜͳ͸ʮϊʯʮϔʯͰϦΞΫγϣϯΛཔΜͩʂ

Slide 5

Slide 5 text

w εϚϗͰ23ίʔυͷಡΈऔΓΛߦͬͨ͜ͱ͕͋Δਓʁ

Slide 6

Slide 6 text

w εϚϗͰ23ίʔυͷಡΈऔΓΛߦͬͨ͜ͱ͕͋Δਓʁ

Slide 7

Slide 7 text

w 23ίʔυͷಡΈऔΓػೳΛ࣮૷ͨ͜͠ͱ͕͋Δਓʁ

Slide 8

Slide 8 text

w 23ಡΈऔΓػೳͷ࣮૷ָ͕͍͠ɾշదɾ΋ͬͱ΍Γ͍ͨਓʁ

Slide 9

Slide 9 text

😢

Slide 10

Slide 10 text

23ίʔυಡΈऔΓ͸ ίʔυ͕ෳࡶʹͳΔ

Slide 11

Slide 11 text

https://developer.apple.com/wwdc22/10025

Slide 12

Slide 12 text

ೖྗσόΠε Χϝϥ ˠ https://developer.apple.com/wwdc22/10025

Slide 13

Slide 13 text

ೖྗσόΠε Χϝϥ ˠ ϓϨϏϡʔදࣔˠ https://developer.apple.com/wwdc22/10025

Slide 14

Slide 14 text

ೖྗσόΠε Χϝϥ ˠ ϓϨϏϡʔදࣔˠ ˡόʔίʔυͷ ɹ৘ใΛऔಘ https://developer.apple.com/wwdc22/10025

Slide 15

Slide 15 text

ೖྗσόΠε Χϝϥ ˠ ϓϨϏϡʔදࣔˠ ˡόʔίʔυͷ ɹ৘ใΛऔಘ ˡೖग़ྗηογϣϯ https://developer.apple.com/wwdc22/10025

Slide 16

Slide 16 text

struct AVFoundationQRCodeScanner: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> UIViewController { let viewController = UIViewController() return viewController } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { } }

Slide 17

Slide 17 text

struct AVFoundationQRCodeScanner: UIViewControllerRepresentable { private let session = AVCaptureSession() private let sessionQueue = DispatchQueue(label: "sessionQueue") func makeUIViewController(context: Context) -> UIViewController { let viewController = UIViewController() return viewController } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { } }

Slide 18

Slide 18 text

struct AVFoundationQRCodeScanner: UIViewControllerRepresentable { private let session = AVCaptureSession() private let sessionQueue = DispatchQueue(label: "sessionQueue") func makeUIViewController(context: Context) -> UIViewController { let viewController = UIViewController() sessionQueue.async { self.configureSession(metadataObjectTypes: [.qr], delegate: context.coordinator) self.session.startRunning() } return viewController } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { } } private extension AVFoundationQRCodeScanner { func configureSession( metadataObjectTypes: [AVMetadataObject.ObjectType], delegate: AVCaptureMetadataOutputObjectsDelegate ) { defer { session.commitConfiguration() } session.beginConfiguration() } }

Slide 19

Slide 19 text

struct AVFoundationQRCodeScanner: UIViewControllerRepresentable { private let session = AVCaptureSession() private let sessionQueue = DispatchQueue(label: "sessionQueue") func makeUIViewController(context: Context) -> UIViewController { let viewController = UIViewController() sessionQueue.async { self.configureSession(metadataObjectTypes: [.qr], delegate: context.coordinator) self.session.startRunning() } return viewController } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { } } private extension AVFoundationQRCodeScanner { func configureSession( metadataObjectTypes: [AVMetadataObject.ObjectType], delegate: AVCaptureMetadataOutputObjectsDelegate ) { defer { session.commitConfiguration() } session.beginConfiguration() let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) guard let videoDevice else { return } do { let videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice) if session.canAddInput(videoDeviceInput) { session.addInput(videoDeviceInput) } } catch { return } } }

Slide 20

Slide 20 text

struct AVFoundationQRCodeScanner: UIViewControllerRepresentable { @Binding var recognizedPayload: String private let session = AVCaptureSession() private let sessionQueue = DispatchQueue(label: "sessionQueue") private let metadataOutput = AVCaptureMetadataOutput() private let metadataObjectQueue = DispatchQueue(label: "metadataObjectQueue") init(recognizedPayload: Binding) { self._recognizedPayload = recognizedPayload } func makeUIViewController(context: Context) -> UIViewController { let viewController = UIViewController() sessionQueue.async { self.configureSession(metadataObjectTypes: [.qr], delegate: context.coordinator) self.session.startRunning() } return viewController } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } final class Coordinator: NSObject, AVCaptureMetadataOutputObjectsDelegate { private let parent: AVFoundationQRCodeScanner init(parent: AVFoundationQRCodeScanner) { self.parent = parent } func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { guard let metadataObject = metadataObjects.first, let machineReadableCode = metadataObject as? AVMetadataMachineReadableCodeObject, machineReadableCode.type == .qr, let stringValue = machineReadableCode.stringValue else { parent.recognizedPayload = "" return } parent.recognizedPayload = stringValue } } } private extension AVFoundationQRCodeScanner { func configureSession( metadataObjectTypes: [AVMetadataObject.ObjectType], delegate: AVCaptureMetadataOutputObjectsDelegate ) { defer { session.commitConfiguration() } session.beginConfiguration() let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) guard let videoDevice else { return } do { let videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice) if session.canAddInput(videoDeviceInput) { session.addInput(videoDeviceInput) } } catch { return } if session.canAddOutput(metadataOutput) { session.addOutput(metadataOutput) metadataOutput.metadataObjectTypes = metadataObjectTypes metadataOutput.setMetadataObjectsDelegate(delegate, queue: metadataObjectQueue) } } }

Slide 21

Slide 21 text

struct AVFoundationQRCodeScanner: UIViewControllerRepresentable { @Binding var recognizedPayload: String private let session = AVCaptureSession() private let sessionQueue = DispatchQueue(label: "sessionQueue") private let metadataOutput = AVCaptureMetadataOutput() private let metadataObjectQueue = DispatchQueue(label: "metadataObjectQueue") private let previewLayer: AVCaptureVideoPreviewLayer init(recognizedPayload: Binding) { self._recognizedPayload = recognizedPayload self.previewLayer = Self.makePreviewLayer(session: self.session) } func makeUIViewController(context: Context) -> UIViewController { let viewController = UIViewController() viewController.view.layer.masksToBounds = true viewController.view.layer.addSublayer(previewLayer) previewLayer.frame = viewController.view.layer.bounds sessionQueue.async { self.configureSession(metadataObjectTypes: [.qr], delegate: context.coordinator) self.session.startRunning() } return viewController } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { previewLayer.frame = uiViewController.view.layer.bounds } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } final class Coordinator: NSObject, AVCaptureMetadataOutputObjectsDelegate { private let parent: AVFoundationQRCodeScanner init(parent: AVFoundationQRCodeScanner) { self.parent = parent } func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { guard let metadataObject = metadataObjects.first, let machineReadableCode = metadataObject as? AVMetadataMachineReadableCodeObject, machineReadableCode.type == .qr, let stringValue = machineReadableCode.stringValue else { parent.recognizedPayload = "" return } parent.recognizedPayload = stringValue } } } private extension AVFoundationQRCodeScanner { func configureSession( metadataObjectTypes: [AVMetadataObject.ObjectType], delegate: AVCaptureMetadataOutputObjectsDelegate ) { defer { session.commitConfiguration() } session.beginConfiguration() let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) guard let videoDevice else { return } do { let videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice) if session.canAddInput(videoDeviceInput) { session.addInput(videoDeviceInput) } } catch { return } if session.canAddOutput(metadataOutput) { session.addOutput(metadataOutput) metadataOutput.metadataObjectTypes = metadataObjectTypes metadataOutput.setMetadataObjectsDelegate(delegate, queue: metadataObjectQueue) } } } private extension AVFoundationQRCodeScanner { static func makePreviewLayer(session: AVCaptureSession) -> AVCaptureVideoPreviewLayer { let layer = AVCaptureVideoPreviewLayer(session: session) layer.videoGravity = .resizeAspectFill layer.connection?.videoOrientation = .portrait return layer } }

Slide 22

Slide 22 text

struct AVFoundationQRCodeScanner: UIViewControllerRepresentable { @Binding var recognizedPayload: String private let session = AVCaptureSession() private let sessionQueue = DispatchQueue(label: "sessionQueue") private let metadataOutput = AVCaptureMetadataOutput() private let metadataObjectQueue = DispatchQueue(label: "metadataObjectQueue") private let previewLayer: AVCaptureVideoPreviewLayer init(recognizedPayload: Binding) { self._recognizedPayload = recognizedPayload self.previewLayer = Self.makePreviewLayer(session: self.session) } func makeUIViewController(context: Context) -> UIViewController { let viewController = UIViewController() viewController.view.layer.masksToBounds = true viewController.view.layer.addSublayer(previewLayer) previewLayer.frame = viewController.view.layer.bounds sessionQueue.async { self.configureSession(metadataObjectTypes: [.qr], delegate: context.coordinator) self.session.startRunning() } return viewController } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { previewLayer.frame = uiViewController.view.layer.bounds } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } final class Coordinator: NSObject, AVCaptureMetadataOutputObjectsDelegate { private let parent: AVFoundationQRCodeScanner init(parent: AVFoundationQRCodeScanner) { self.parent = parent } func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { guard let metadataObject = metadataObjects.first, let machineReadableCode = metadataObject as? AVMetadataMachineReadableCodeObject, machineReadableCode.type == .qr, let stringValue = machineReadableCode.stringValue else { parent.recognizedPayload = "" return } parent.recognizedPayload = stringValue } } } private extension AVFoundationQRCodeScanner { func configureSession( metadataObjectTypes: [AVMetadataObject.ObjectType], delegate: AVCaptureMetadataOutputObjectsDelegate ) { defer { session.commitConfiguration() } session.beginConfiguration() let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) guard let videoDevice else { return } do { let videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice) if session.canAddInput(videoDeviceInput) { session.addInput(videoDeviceInput) } } catch { return } if session.canAddOutput(metadataOutput) { session.addOutput(metadataOutput) metadataOutput.metadataObjectTypes = metadataObjectTypes metadataOutput.setMetadataObjectsDelegate(delegate, queue: metadataObjectQueue) } } } private extension AVFoundationQRCodeScanner { static func makePreviewLayer(session: AVCaptureSession) -> AVCaptureVideoPreviewLayer { let layer = AVCaptureVideoPreviewLayer(session: session) layer.videoGravity = .resizeAspectFill layer.connection?.videoOrientation = .portrait return layer } } 😫

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

DataScannerViewController

Slide 25

Slide 25 text

%BUB4DBOOFS7JFX$POUSPMMFS w 7JTJPO,JUϑϨʔϜϫʔΫʹΑͬͯఏڙ w 6*7JFX$POUSPMMFSͷαϒΫϥε w J04Ҏ্Ͱར༻͢Δ͜ͱ͕Մೳ w Ұ෦୺຤Ͱ͸ར༻͢Δ͜ͱ͕Ͱ͖ͳ͍

Slide 26

Slide 26 text

7JTJPOWT7JTJPO,JU w ίϯϐϡʔλϏδϣϯΞϧΰϦζϜΛ 
 ར༻ͯ͠ɺը૾ॲཧɾಈըॲཧΛߦ͏ w ػցֶशϞσϧΛར༻ w ΧϝϥΛར༻ͨ͠৘ใͷݕग़΍ɺ 
 औಘͨ͠৘ใΛදࣔ͢Δ6*Λఏڙ͢Δ w ಺෦ͷը૾ॲཧͰ͸7JTJPO͕ಈ͍͍ͯΔʁ 7JTJPO 7JTJPO,JU

Slide 27

Slide 27 text

%BUB4DBOOFS7JFX$POUSPMMFSͷ஫ҙ఺ w ೥Ҏ߱ͷ/FVSBM&OHJOFΛ౥ࡌͨ͠୺຤Ͱ͔͠ಈ࡞͠ͳ͍ w DataScannerViewController.isSupportedͰ 
 ར༻Մೳͳ୺຤͔൑ఆͰ͖Δ

Slide 28

Slide 28 text

σϞ

Slide 29

Slide 29 text

struct VisionKitQRCodeScanner: UIViewControllerRepresentable { @Binding var recognizedPayload: String func makeUIViewController(context: Context) -> DataScannerViewController { let dataScannerViewController = DataScannerViewController( recognizedDataTypes: [.barcode(symbologies: [.qr])] ) dataScannerViewController.delegate = context.coordinator try? dataScannerViewController.startScanning() return dataScannerViewController } func updateUIViewController(_ uiViewController: DataScannerViewController, context: Context) { } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } final class Coordinator: NSObject, DataScannerViewControllerDelegate { private let parent: VisionKitQRCodeScanner init(parent: VisionKitQRCodeScanner) { self.parent = parent } func dataScanner(_ dataScanner: DataScannerViewController, didAdd addedItems: [RecognizedItem], allItems: [RecognizedItem]) { guard case .barcode(let barcode) = addedItems.first else { return } if let payloadStringValue = barcode.payloadStringValue { parent.recognizedPayload = payloadStringValue } } func dataScanner(_ dataScanner: DataScannerViewController, didRemove removedItems: [RecognizedItem], allItems: [RecognizedItem]) { parent.recognizedPayload = "" } } } ΊͪΌͪ͘Όγϯϓϧʂʂʂ

Slide 30

Slide 30 text

struct VisionKitQRCodeScanner: UIViewControllerRepresentable { @Binding var recognizedPayload: String func makeUIViewController(context: Context) -> DataScannerViewController { let dataScannerViewController = DataScannerViewController( recognizedDataTypes: [.barcode(symbologies: [.qr])] ) dataScannerViewController.delegate = context.coordinator try? dataScannerViewController.startScanning() return dataScannerViewController } func updateUIViewController(_ uiViewController: DataScannerViewController, context: Context) { } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } final class Coordinator: NSObject, DataScannerViewControllerDelegate { private let parent: VisionKitQRCodeScanner init(parent: VisionKitQRCodeScanner) { self.parent = parent } func dataScanner(_ dataScanner: DataScannerViewController, didAdd addedItems: [RecognizedItem], allItems: [RecognizedItem]) { guard case .barcode(let barcode) = addedItems.first else { return } if let payloadStringValue = barcode.payloadStringValue { parent.recognizedPayload = payloadStringValue } } func dataScanner(_ dataScanner: DataScannerViewController, didRemove removedItems: [RecognizedItem], allItems: [RecognizedItem]) { parent.recognizedPayload = "" } } } struct AVFoundationQRCodeScanner: UIViewControllerRepresentable { @Binding var recognizedPayload: String private let session = AVCaptureSession() private let sessionQueue = DispatchQueue(label: "sessionQueue") private let metadataOutput = AVCaptureMetadataOutput() private let metadataObjectQueue = DispatchQueue(label: "metadataObjectQueue") private let previewLayer: AVCaptureVideoPreviewLayer init(recognizedPayload: Binding) { self._recognizedPayload = recognizedPayload self.previewLayer = Self.makePreviewLayer(session: self.session) } func makeUIViewController(context: Context) -> UIViewController { let viewController = UIViewController() viewController.view.layer.masksToBounds = true viewController.view.layer.addSublayer(previewLayer) previewLayer.frame = viewController.view.layer.bounds sessionQueue.async { self.configureSession(metadataObjectTypes: [.qr], delegate: context.coordinator) self.session.startRunning() } return viewController } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { previewLayer.frame = uiViewController.view.layer.bounds } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } final class Coordinator: NSObject, AVCaptureMetadataOutputObjectsDelegate { private let parent: AVFoundationQRCodeScanner init(parent: AVFoundationQRCodeScanner) { self.parent = parent } func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { guard let metadataObject = metadataObjects.first, let machineReadableCode = metadataObject as? AVMetadataMachineReadableCodeObject, machineReadableCode.type == .qr, let stringValue = machineReadableCode.stringValue else { parent.recognizedPayload = "" return } parent.recognizedPayload = stringValue } } } private extension AVFoundationQRCodeScanner { func configureSession( metadataObjectTypes: [AVMetadataObject.ObjectType], delegate: AVCaptureMetadataOutputObjectsDelegate ) { defer { session.commitConfiguration() } session.beginConfiguration() let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) guard let videoDevice else { return } do { let videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice) if session.canAddInput(videoDeviceInput) { session.addInput(videoDeviceInput) } } catch { return } if session.canAddOutput(metadataOutput) { session.addOutput(metadataOutput) metadataOutput.metadataObjectTypes = metadataObjectTypes metadataOutput.setMetadataObjectsDelegate(delegate, queue: metadataObjectQueue) } } } private extension AVFoundationQRCodeScanner { static func makePreviewLayer(session: AVCaptureSession) -> AVCaptureVideoPreviewLayer { let layer = AVCaptureVideoPreviewLayer(session: session) layer.videoGravity = .resizeAspectFill layer.connection?.videoOrientation = .portrait return layer } } 7JTJPO,JU "7'PVOEBUJPO

Slide 31

Slide 31 text

ΧϝϥىಈɾϓϨϏϡʔදࣔɾεΩϟϯ։࢝ struct VisionKitQRCodeScanner: UIViewControllerRepresentable { @Binding var recognizedPayload: String func makeUIViewController(context: Context) -> DataScannerViewController { let dataScannerViewController = DataScannerViewController( recognizedDataTypes: [.barcode(symbologies: [.qr])] ) dataScannerViewController.delegate = context.coordinator try? dataScannerViewController.startScanning() return dataScannerViewController } func updateUIViewController(_ uiViewController: DataScannerViewController, context: Context) { } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } final class Coordinator: NSObject, DataScannerViewControllerDelegate { private let parent: VisionKitQRCodeScanner init(parent: VisionKitQRCodeScanner) { self.parent = parent } func dataScanner(_ dataScanner: DataScannerViewController, didAdd addedItems: [RecognizedItem], allItems: [RecognizedItem]) { guard case .barcode(let barcode) = addedItems.first else { return } if let payloadStringValue = barcode.payloadStringValue { parent.recognizedPayload = payloadStringValue } } func dataScanner(_ dataScanner: DataScannerViewController, didRemove removedItems: [RecognizedItem], allItems: [RecognizedItem]) { parent.recognizedPayload = "" } } }

Slide 32

Slide 32 text

ΧϝϥىಈɾϓϨϏϡʔදࣔɾεΩϟϯ։࢝ func makeUIViewController(context: Context) -> DataScannerViewController { let dataScannerViewController = DataScannerViewController( recognizedDataTypes: [.barcode(symbologies: [.qr])] ) dataScannerViewController.delegate = context.coordinator try? dataScannerViewController.startScanning() return dataScannerViewController }

Slide 33

Slide 33 text

ΧϝϥىಈɾϓϨϏϡʔදࣔɾεΩϟϯ։࢝ func makeUIViewController(context: Context) -> DataScannerViewController { let dataScannerViewController = DataScannerViewController( recognizedDataTypes: [.barcode(symbologies: [.qr])] ) dataScannerViewController.delegate = context.coordinator try? dataScannerViewController.startScanning() return dataScannerViewController }

Slide 34

Slide 34 text

23ίʔυͷ৘ใΛऔಘ struct VisionKitQRCodeScanner: UIViewControllerRepresentable { @Binding var recognizedPayload: String func makeUIViewController(context: Context) -> DataScannerViewController { let dataScannerViewController = DataScannerViewController( recognizedDataTypes: [.barcode(symbologies: [.qr])] ) dataScannerViewController.delegate = context.coordinator try? dataScannerViewController.startScanning() return dataScannerViewController } func updateUIViewController(_ uiViewController: DataScannerViewController, context: Context) { } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } final class Coordinator: NSObject, DataScannerViewControllerDelegate { private let parent: VisionKitQRCodeScanner init(parent: VisionKitQRCodeScanner) { self.parent = parent } func dataScanner(_ dataScanner: DataScannerViewController, didAdd addedItems: [RecognizedItem], allItems: [RecognizedItem]) { guard case .barcode(let barcode) = addedItems.first else { return } if let payloadStringValue = barcode.payloadStringValue { parent.recognizedPayload = payloadStringValue } } func dataScanner(_ dataScanner: DataScannerViewController, didRemove removedItems: [RecognizedItem], allItems: [RecognizedItem]) { parent.recognizedPayload = "" } } }

Slide 35

Slide 35 text

23ίʔυͷ৘ใΛऔಘ final class Coordinator: NSObject, DataScannerViewControllerDelegate { ... /// σʔλεΩϟφ͕ΞΠςϜͷೝࣝΛ։࢝͢ΔͱԠ౴͠·͢ɻ func dataScanner(_ dataScanner: DataScannerViewController, didAdd addedItems: [RecognizedItem], allItems: [RecognizedItem]) { guard case .barcode(let barcode) = addedItems.first else { return } if let payloadStringValue = barcode.payloadStringValue { parent.recognizedPayload = payloadStringValue } } /// σʔλεΩϟφ͕ΞΠςϜͷೝࣝΛఀࢭͨ͠ͱ͖ʹԠ౴͠·͢ɻ func dataScanner(_ dataScanner: DataScannerViewController, didRemove removedItems: [RecognizedItem], allItems: [RecognizedItem]) { parent.recognizedPayload = "" } }

Slide 36

Slide 36 text

23ίʔυͷ৘ใΛऔಘ final class Coordinator: NSObject, DataScannerViewControllerDelegate { ... /// σʔλεΩϟφ͕ΞΠςϜͷೝࣝΛ։࢝͢ΔͱԠ౴͠·͢ɻ func dataScanner(_ dataScanner: DataScannerViewController, didAdd addedItems: [RecognizedItem], allItems: [RecognizedItem]) { guard case .barcode(let barcode) = addedItems.first else { return } if let payloadStringValue = barcode.payloadStringValue { parent.recognizedPayload = payloadStringValue } } /// σʔλεΩϟφ͕ΞΠςϜͷೝࣝΛఀࢭͨ͠ͱ͖ʹԠ౴͠·͢ɻ func dataScanner(_ dataScanner: DataScannerViewController, didRemove removedItems: [RecognizedItem], allItems: [RecognizedItem]) { parent.recognizedPayload = "" } }

Slide 37

Slide 37 text

ػೳΛ௥Ճͯ͠ΈΔ

Slide 38

Slide 38 text

ϑΥʔΧεதͷ 
 23ίʔυʹ 
 ϋΠϥΠτΛදࣔ

Slide 39

Slide 39 text

ΧϝϥىಈɾϓϨϏϡʔදࣔɾεΩϟϯ։࢝ let dataScannerViewController = DataScannerViewController( recognizedDataTypes: [.barcode(symbologies: [.qr])], isHighlightingEnabled: true )

Slide 40

Slide 40 text

23ίʔυλοϓ࣌ͷ 
 ΞΫγϣϯΛ௥Ճ

Slide 41

Slide 41 text

23ίʔυλοϓ࣌ͷΞΫγϣϯΛ௥Ճ final class Coordinator: NSObject, DataScannerViewControllerDelegate { ... /// σʔλεΩϟφ͕ೝࣝͨ͠ΞΠςϜΛਓ͕λοϓ͢ΔͱԠ౴͠·͢ɻ func dataScanner(_ dataScanner: DataScannerViewController, didTapOn item: RecognizedItem) { guard case .barcode(let barcode) = item else { return } if let payloadStringValue = barcode.payloadStringValue, let url = URL(string: payloadStringValue) { UIApplication.shared.open(url) } } }

Slide 42

Slide 42 text

%BUB4DBOOFS7JFX$POUSPMMFS͕Ͱ͖Δ͜ͱ w ΠχγϟϥΠβͰσʔλεΩϟφͷΦϓγϣϯΛઃఆ͢Δ͜ͱ͕Ͱ͖Δ w recognizedDataTypesͷ஋Λઃఆ͢Δ͜ͱͰɺςΩετͷಡΈऔΓ΋Մೳ w ಡΈऔΓͷਫ਼౓ɺෳ਺ͷ23ίʔυΛಉ࣌ʹೝࣝ͢Δ͔ɺͳͲΛࢦఆͰ͖Δ w εΩϟϯதͷ23ίʔυͷҐஔ͕มΘͬͨͱ͖΍ΧϝϥͷζʔϜഒ཰Λ 
 มߋͨ͠ࡍͷΠϕϯτ΋%FMFHBUFͰϋϯυϦϯάͰ͖Δ

Slide 43

Slide 43 text

struct VisionKitQRCodeScanner: UIViewControllerRepresentable { @Binding var recognizedPayload: String func makeUIViewController(context: Context) -> DataScannerViewController { let dataScannerViewController = DataScannerViewController( recognizedDataTypes: [.barcode(symbologies: [.qr])], isHighlightingEnabled: true ) dataScannerViewController.delegate = context.coordinator try? dataScannerViewController.startScanning() return dataScannerViewController } func updateUIViewController(_ uiViewController: DataScannerViewController, context: Context) { } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } final class Coordinator: NSObject, DataScannerViewControllerDelegate { private let parent: VisionKitQRCodeScanner init(parent: VisionKitQRCodeScanner) { self.parent = parent } func dataScanner(_ dataScanner: DataScannerViewController, didAdd addedItems: [RecognizedItem], allItems: [RecognizedItem]) { guard case .barcode(let barcode) = addedItems.first else { return } if let payloadStringValue = barcode.payloadStringValue { parent.recognizedPayload = payloadStringValue } } func dataScanner(_ dataScanner: DataScannerViewController, didRemove removedItems: [RecognizedItem], allItems: [RecognizedItem]) { parent.recognizedPayload = "" } func dataScanner(_ dataScanner: DataScannerViewController, didTapOn item: RecognizedItem) { guard case .barcode(let barcode) = item else { return } if let payloadStringValue = barcode.payloadStringValue, let url = URL(string: payloadStringValue) { UIApplication.shared.open(url) } } } }

Slide 44

Slide 44 text

·ͱΊ w "7'PVOEBUJPOΛ࢖࣮ͬͨ૷͸ෳࡶʹͳΓ͕ͪ w %BUB4DBOOFS7JFX$POUSPMMFSΛ࢖͏͜ͱͰ؆୯ʹػೳΛ࣮૷Ͱ͖Δ w J04΍J1IPOFͷόʔδϣϯʹΑͬͯ͸%BUB4DBOOFS7JFX$POUSPMMFS͕ 
 ࢖͑ͳ͍͜ͱ΋͋ΔͷͰɺ࠾༻͢Δ࣌͸஫ҙ͕ඞཁ

Slide 45

Slide 45 text

͓ΘΓʹ w ࠷ॳʹݴͬͨ͜ͱΛ֮͑ͯ·͔͢ʜʁ

Slide 46

Slide 46 text

w 23ಡΈऔΓػೳָ͕͘͠ɾ؆୯ʹ࣮૷Ͱ͖ͦ͏ͩͳͱࢥͬͨਓʂ

Slide 47

Slide 47 text

😄

Slide 48

Slide 48 text

એ఻ ೔෇ɿ ۚ ৔ॴɿେࡕകాΦϯϥΠϯ഑৴ DPOOQBTT 5XJUUFS