Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 웹뷰
- Git
- iOS16
- darkmode
- Session
- IOS
- MacOS
- FLUTTER
- UIButton
- JPA
- SwiftUI
- Code
- geofencing
- github
- Realm
- Archive
- 한글
- rxswift
- 이미지
- Firebase
- error
- 개발자
- Apple
- Swift
- Notification
- Xcode
- window
- view
- mac
- appstore
Archives
- Today
- Total
EEYatHo 앱 깎는 이야기
Swift ) QRCodeScanner - EEYatHo iOS 본문
반응형
4개 파일로 간단히 구현.
UIKit의 ViewController로 QR기능을 구현 한 뒤, SwiftUI로 변경하는 예시코드들.
ContentView
import SwiftUI
struct ContentView: View {
@State private var uriFromQR: String = ""
var body: some View {
ZStack {
// QR Scanner
QRCameraView(uriFromQR: $uriFromQR)
VStack {
Spacer()
// Scan 한 값을 보여주는 Text
Text(uriFromQR)
.padding(EdgeInsets(top: 0, leading: 15, bottom: 0, trailing: 15))
.minimumScaleFactor(0.1)
.frame(width: UIScreen.main.bounds.width - 48, height: 48, alignment: .leading)
.border(Color.gray, width: 1)
Spacer().frame(height: 70)
}
}
}
}
QRCameraView
import SwiftUI
struct QRCameraView: View {
@Binding var uriFromQR: String
let uriFromQRFromController = NotificationCenter.default
.publisher(for: NSNotification.Name("URI Recognized By QR"))
var body: some View {
QRCameraRepresentable()
.onReceive(uriFromQRFromController) { (output) in
uriFromQR = output.object as? String ?? ""
}
}
}
QRCameraRepresentable
import SwiftUI
struct QRCameraRepresentable: UIViewControllerRepresentable {
// 뷰컨트롤러 첫 생성
func makeUIViewController(context: Context) -> QRCameraController {
QRCameraController()
}
// 첫 생성 이후에는 해당 메소드가 호출.
func updateUIViewController(_ cameraViewController: QRCameraController, context: Context) {}
}
QRCameraController
import UIKit
import AVFoundation
final class QRCameraController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
// 카메라에 QR코드가 인식되면 호출. (1초에 수십번 호출됨)
// 인식된 이미지에서 QR 값 확인 후, 이전과 다른 uri라면 Notification.
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
guard let readableObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
let uriFromQR = readableObject.stringValue else { return }
if previousURI != uriFromQR {
previousURI = uriFromQR
NotificationCenter.default.post(name: NSNotification.Name("URI Recognized By QR"), object: uriFromQR, userInfo: nil)
print("📷 uri from QR:", uriFromQR)
}
}
// 실시간 캡처 활동을 관리하고, 입력 장치의 데이터 흐름을 조정하여 출력을 캡처하는 Object
private let captureSession = AVCaptureSession()
// 후면 카메라
private var backCamera: AVCaptureDevice!
// 이전 uri 저장용
private var previousURI: String = ""
override func viewDidLoad() {
super.viewDidLoad()
do {
try getBackCamera()
try setupCaptureSession()
} catch {
print("📷", error)
}
setupPreviewLayer()
startRunningCaptureSession()
}
// 1. 후면 카메라 가져오기
private func getBackCamera() throws {
let session = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .unspecified)
guard let backCamera = session.devices.first(where: { $0.position == .back }) else {
throw NSError(domain: "후면 카메라를 찾지 못했습니다.", code: 404)
}
self.backCamera = backCamera
}
// 2. 캡처 세션 설정
private func setupCaptureSession() throws {
// 출력 품질 설정
captureSession.sessionPreset = .photo
// 후면 카메라를 Input으로 설정
let captureDeviceInput = try AVCaptureDeviceInput(device: backCamera)
captureSession.addInput(captureDeviceInput)
// QR 메타데이터를 Output으로 설정
let metadataOutput = AVCaptureMetadataOutput()
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = [.qr]
}
// 3. 카메라 프리뷰 Layer 설정
private func setupPreviewLayer() {
let cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
cameraPreviewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
if #available(iOS 17.0, *) {
cameraPreviewLayer.connection?.videoRotationAngle = 90 // 0(오른), 90(정상), 180(왼), 270(뒤집힌)
} else {
cameraPreviewLayer.connection?.videoOrientation = .portrait
}
cameraPreviewLayer.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height) // FullScreen 아닌 경우, 해당 부분 수정
view.layer.insertSublayer(cameraPreviewLayer, at: 0)
}
// 4. Capture Session을 시작 (카메라 화면이 나오며, 동작하기 시작)
private func startRunningCaptureSession() {
DispatchQueue.global().async { [weak self] in
self?.captureSession.startRunning() // main thread 에서 호출될 시, 보라색 경고 발생
}
}
}
Project Link
https://github.com/EE-Yat-Ho/QRCodeScanner
GitHub - EE-Yat-Ho/QRCodeScanner
Contribute to EE-Yat-Ho/QRCodeScanner development by creating an account on GitHub.
github.com
'iOS, Swift > Feature' 카테고리의 다른 글
Swift ) 만보기 모듈 CoreMotion - EEYatHo iOS (0) | 2023.06.29 |
---|---|
Swift ) HapticEngine 진동. 원하는 패턴. 무한반복 - EEYatHo iOS (0) | 2022.10.28 |
Swift ) AttributedString 에 이미지 넣기 - EEYatHo iOS (0) | 2022.10.11 |
Swift ) Crashlytics dSYM 자동 업로드 - EEYatHo iOS (1) | 2022.06.30 |
Swift ) 이미지 다운로드, 캐싱 - EEYatHo iOS (0) | 2022.06.21 |
Comments