[UIKit] Face ID & Touch ID

Junyoung Park·2022년 12월 24일
0

UIKit

목록 보기
126/142
post-thumbnail

Face ID & Touch ID Usage in App (Swift 5, Xcode 12, Biometrics, iOS) - 2022 iOS Development

Face ID & Touch ID

구현 목표

  • 얼굴/지문 인식 구현

구현 태스크

  • 생체 인증 로직 구현
  • alert 및 성공 표시를 위한 UI 구현

핵심 코드

@objc private func didTapAuth() {
        let context = LAContext()
        var error: NSError?
        if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
            let reason = "Please authorize with your Bio-ID"
            context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { [weak self] success, error in
                guard
                    success,
                    error == nil else {
                    self?.showAlert(title: "Failed to Authenticate", message: "Please try again")
                    return
                }
                DispatchQueue.main.async { [weak self] in
                    self?.resultLabel.text = "Authentication Passed"
                }
            }
        } else {
            showAlert(title: "Unavaiable", message: "You cannot use this service")
        }
    }
  • LocalAuthentication 모듈을 임포트한 뒤 LAContext를 사용
  • 현재 생체 인증을 사용할 수 있는 디바이스가 아니라면 alert
  • 생체 인증을 할 수 있다면 evaluatePolicy를 통해 얼굴/지문 인식 → 컴플리션 핸들러를 통해 리턴되는 불리언 변수를 통해 인증 성공 여부를 체크 가능

소스 코드

import LocalAuthentication
import UIKit

final class BioAuthViewController: UIViewController {
    private lazy var authButton: UIButton = {
        let button = UIButton()
        var config = UIButton.Configuration.filled()
        config.title = "Auth"
        config.baseForegroundColor = .white
        config.baseBackgroundColor = .systemGreen
        button.configuration = config
        button.addTarget(self, action: #selector(didTapAuth), for: .touchUpInside)
        return button
    }()
    private let resultLabel: UILabel = {
        let label = UILabel()
        label.font = .preferredFont(forTextStyle: .body)
        label.textColor = .label
        label.textAlignment = .center
        label.numberOfLines = 0
        label.text = "Not Authenticated yet"
        return label
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        setUI()
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        authButton.frame = CGRect(x: 0, y: 0, width: 200, height: 50)
        authButton.center = view.center
        resultLabel.frame = CGRect(x: 0, y: authButton.frame.origin.y - 100, width: view.frame.size.width, height: 100)
    }
    
    private func setUI() {
        title = "Bio Auth"
        navigationItem.largeTitleDisplayMode = .always
        navigationController?.navigationBar.prefersLargeTitles = true
        view.addSubview(authButton)
        view.addSubview(resultLabel)
        view.backgroundColor = .systemBackground
    }
    
    @objc private func didTapAuth() {
        let context = LAContext()
        var error: NSError?
        if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
            let reason = "Please authorize with your Bio-ID"
            context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { [weak self] success, error in
                guard
                    success,
                    error == nil else {
                    self?.showAlert(title: "Failed to Authenticate", message: "Please try again")
                    return
                }
                DispatchQueue.main.async { [weak self] in
                    self?.resultLabel.text = "Authentication Passed"
                }
            }
        } else {
            showAlert(title: "Unavaiable", message: "You cannot use this service")
        }
    }
    
    private func showAlert(title: String, message: String) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
        DispatchQueue.main.async { [weak self] in
            self?.present(alert, animated: true)
        }
    }

}
  • 생체 인증 컴플리션이 실행되는 스레드는 메인 스레드가 아니기 때문에 결과값을 통해 UI에 표시할 때 메인 스레드에 별도로 넣어주기

구현 화면

profile
JUST DO IT

0개의 댓글