Notice
Recent Posts
Recent Comments
Link
투케이2K
36. (Objective-C/objc) A_Auth - 간편 지문 , 얼굴 인증 수행 클래스 정의 실시 본문
[개발 환경 설정]
개발 툴 : XCODE
개발 언어 : OBJECTIVE-C
[사전 info plist 설정 필요]
[소스 코드]
import UIKit
// MARK: [import 추가 실시]
import LocalAuthentication
@objc class A_Auth: NSObject {
// MARK: [클래스 설명]
/*
// -----------------------------------------
1. A_Auth : 생체 인증 수행 액티비티
// -----------------------------------------
2. info.plist 권한 등록 필요 :
- Privacy - Face ID Usage Description
// -----------------------------------------
3. import 추가 필요 :
- import LocalAuthentication
// -----------------------------------------
*/
// MARK: [간편 지문 인증 사용 방법]
/*
// -----------------------------------------
1. 간편 지문 인증 수행 > 자동으로 권한 체크 > 잠금 설정 체크 > 지문 인증 성공 결과 및 에러 메시지 받음
// -----------------------------------------
2. Objective-C 소스코드에서 Swift 소스코드 사용 참고 사이트 :
// MARK: [참고 사이트 주소]
https://blog.naver.com/kkh0977/222785528528
// -----------------------------------------
3. Objective-C 소스코드에서 Swift 사용을 위해 import 등록
// MARK: [프로젝트명칭-Swift.h import 명시]
#import "objectiveProject-Swift.h"
// -----------------------------------------
4. 액티비티 메모리 로드 [viewDidLoad] : 노티피케이션 채널 알림 등록
// MARK: [노티피케이션 알림 채널 등록]
NSNotificationCenter *simpleAuthNotification = [NSNotificationCenter defaultCenter]; // [객체 선언 실시]
[simpleAuthNotification addObserver:self selector:@selector(simpleAuthNotification:) name:[A_Auth NOTI_CHANNER] object:nil]; // [채널 등록 실시]
// -----------------------------------------
5. 액티비티 수행 종료 [viewDidDisappear] : 노티피케이션 채널 알림 해제
// MARK: [노티피케이션 알림 채널 해제]
NSNotificationCenter *simpleAuthNotification = [NSNotificationCenter defaultCenter]; // [객체 선언 실시]
[simpleAuthNotification removeObserver:self name:[A_Auth NOTI_CHANNER] object:nil]; // [채널 해제 실시]
// -----------------------------------------
6. 실시간 간편 인증 수행 결과를 받을 수 있는 리시버 등록 실시
// MARK: - [실시간 노티피케이션 알림 수신 (받는) 부분]
-(void)simpleAuthNotification:(NSNotification *)notification {
printf("\n");
printf("==================================== \n");
printf("[ViewController >> simpleAuthNotification() :: 간편 인증 결과 채널 알림 전달 받음] \n");
printf("==================================== \n");
printf("\n");
// [딕셔너리로 전달 받은 데이터 파싱]
NSString *msgData = [[notification userInfo] objectForKey:@"message"];
printf("\n");
printf("==================================== \n");
printf("[ViewController >> simpleAuthNotification() :: 간편 인증 결과 확인] \n");
printf("[msgData : %s] \n", msgData.description.UTF8String);
printf("==================================== \n");
printf("\n");
// [간편 인증 결과가 성공 및 실패인 경우 로직 처리 실시]
if ([[String_Ext shared] equalsWith_oneString:msgData _twoString:[A_Auth CHECK_SUCCESS]] == true){ // MARK: [간편 지문 인증 등록 성공]
// [팝업창 알림 실시]
[[A_Auth shared] showAlertWithView:self tittle:@"[간편 인증 결과]" content:msgData okBtb:@"확인" noBtn:@"취소"];
}
else { // MARK: [에러 발생 메시지 인 경우]
// [팝업창 알림 실시]
[[A_Auth shared] showAlertWithView:self tittle:@"[간편 인증 결과]" content:msgData okBtb:@"확인" noBtn:@"취소"];
}
}
// -----------------------------------------
7. 뷰 화면 표시 [viewDidAppear] : 간편 인증 기능 수행 실시
// MARK: [간편 인증 기능 수행]
[[A_Auth shared] simpleAuthWithView:self];
// -----------------------------------------
*/
// MARK: [클래스 싱글톤 생성 실시]
@objc static let shared = A_Auth()
// MARK: - [전역 변수 선언 실시]
private let context = LAContext() // [생체 인증 객체]
private let policy: LAPolicy // [deviceOwnerAuthenticationWithBiometrics 객체]
private let localizedReason: String // [생체 인증 팝업창 내용]
private var error: NSError? // [에러 발생 타입]
static let POPUP_CONTENT = "생체 인증을 수행합니다." // [생체 인증 팝업창 내용]
static let POPUP_FALLBACK = "" // [생체 인증 팝업창 버튼 내용]
static let POPUP_CANCLE = "취소" // [생체 인증 팝업창 버튼 내용]
static let ERROR_CHECK_FAIL = "ERROR CHECK FAIL" // [에러 체크 실패 멘트 저장]
@objc static let CHECK_SUCCESS = "SUCCESS" // [생체 인증 사용 여부 및 생체 인증 결과 성공 멘트 저장]
@objc static let NOTI_CHANNER = "simpleAuthNotification" // [노티피케이션 브로드 캐스팅 채널 알림 등록]
// MARK: - [클래스 생성자 초기화 실시 : 생체 인증 팝업창 내용 표시 설정]
init(policy: LAPolicy = .deviceOwnerAuthenticationWithBiometrics,
localizedReason: String = A_Auth.POPUP_CONTENT,
localizedFallbackTitle: String = A_Auth.POPUP_FALLBACK,
localizedCancelTitle: String = A_Auth.POPUP_CANCLE) {
// [전역 변수에 매핑 실시]
self.policy = policy
self.localizedReason = localizedReason
self.context.localizedFallbackTitle = localizedFallbackTitle
self.context.localizedCancelTitle = localizedCancelTitle
}
// MARK: - [생체 인증 타입 정의]
enum BiometricType {
case none
case touchID
case faceID
case unknown
}
@available(iOS 11.0, *) // [특정 IOS 버전 이상 사용 가능]
private func biometricType(for type: LABiometryType) -> BiometricType {
switch type {
case .none:
return .none
case .touchID:
return .touchID
case .faceID:
return .faceID
@unknown default:
return .unknown
}
}
// MARK: - [생체 인증 에러 메시지 리턴 수행 부분]
@available(iOS 11.0, *) // [특정 IOS 버전 이상 사용 가능]
private func biometricError(from nsError: NSError) -> (Int, String) {
var retry = 0 // 재실행 여부
var error = "" // 에러 메시지
switch nsError {
// MARK: [생체 인증에 실패하였습니다. 재실행하시겠습니까?]
case LAError.authenticationFailed:
retry = 1
error = "생체 인증에 실패하였습니다. 재실행하시겠습니까?"
// MARK: [생체 인증 동작을 취소하였습니다. 재실행하시겠습니까?]
case LAError.userCancel:
retry = 1
error = "생체 인증 동작을 취소하였습니다. 재실행하시겠습니까?"
// MARK: [생체 인증 기능이 필요합니다. 재실행하시겠습니까?]
case LAError.userFallback:
retry = 1
error = "생체 인증 기능이 필요합니다. 재실행하시겠습니까?"
// MARK: [기기에서 생체 인식을 사용할 수 없습니다. 권한을 거부하신 경우 확인해주세요.]
case LAError.biometryNotAvailable:
retry = 0
error = "기기에서 생체 인식을 사용할 수 없습니다. 권한을 거부하신 경우 확인해주세요."
// MARK: [등록된 생체 인식 ID가 없습니다. 생체 인증 등록 후 사용해 주세요.]
case LAError.biometryNotEnrolled:
retry = 0
error = "등록된 생체 인식 ID가 없습니다. 생체 인증 등록 후 사용해 주세요."
// MARK: [생체 인증 사용 잠금 (LOCK) 상태입니다. 디바이스에 등록된 생체 인증을 확인 후 다시 실행해주세요.]
case LAError.biometryLockout:
retry = 0
error = "생체 인증 사용 잠금 (LOCK) 상태입니다. 디바이스에 등록된 생체 인증을 확인 후 다시 실행해주세요."
// MARK: [생체 인증 기능 동작이 취소되었습니다. 잠시후 다시 실행해주세요.]
case LAError.appCancel:
retry = 0
error = "생체 인증 기능 동작이 취소되었습니다. 잠시후 다시 실행해주세요."
// MARK: [생체 인증에서 일시적인 문제가 발생하였습니다.]
default:
retry = 0
error = "생체 인증에서 일시적인 문제가 발생하였습니다. 잠시후 다시 실행해주세요."
}
/*
print("")
print("====================================")
print("[A_Auth >> biometricError() :: 생체 인증 에러 메시지 반환 실시]")
print("error :: ", error)
print("====================================")
print("")
// */
return (retry, error)
}
// MARK: - [생체 인증 수행 >> 사용 가능 여부 판단]
@available(iOS 11.0, *) // [특정 IOS 버전 이상 사용 가능]
func canEvaluate() -> Dictionary<String, Any> {
print("")
print("====================================")
print("[A_Auth >> canEvaluate() :: 생체 인증 [사용] 가능 여부 [판단] 실시]")
print("====================================")
print("")
// [세마포어 선언 : 프로그램 로직을 동기화 구현]
let semaphore = DispatchSemaphore(value: 0) // [value 0 값은 대기 상태 선언]
var returnDic : Dictionary<String, Any> = [String : Any]() // 리턴 딕셔너리
var errorData : NSError? = nil // 에러 타입
var errorMsg = "" // 에러 메시지
guard self.context.canEvaluatePolicy(self.policy, error: &self.error) else {
// [생체 인증 타입 매핑]
let type = self.biometricType(for: self.context.biometryType)
// [에러 체크 문제 발생]
guard let error = self.error
else {
print("")
print("====================================")
print("[A_Auth >> canEvaluate() :: 생체 인증 [사용] 가능 [결과] 확인]")
print("결과 :: 에러 체크 실패")
print("type :: ", type)
print("error :: ", error?.localizedDescription ?? "")
print("====================================")
print("")
// [생체 인증 사용 가능 여부 에러 결과 반환]
returnDic["result"] = false
returnDic["msg"] = A_Auth.ERROR_CHECK_FAIL
// [세마포어 신호 알림]
semaphore.signal()
// [리턴 데이터 반환]
return returnDic
}
// [에러 타입 삽입 실시]
errorData = error as NSError
print("")
print("====================================")
print("[A_Auth >> canEvaluate() :: 생체 인증 [사용] 가능 [결과] 확인]")
print("결과 :: 사용 불가능")
print("type :: ", type)
print("retry :: ", self.biometricError(from: errorData as! NSError).0)
print("msg :: ", self.biometricError(from: errorData as! NSError).1)
print("====================================")
print("")
// [에러 메시지 삽입]
errorMsg = self.biometricError(from: errorData!).1 // [에러 메시지]
// [에러 발생 데이터 생성 실시]
returnDic["result"] = false
returnDic["msg"] = errorMsg
// [세마포어 신호 알림]
semaphore.signal()
// [리턴 데이터 반환]
return returnDic
}
print("")
print("====================================")
print("[A_Auth >> canEvaluate() :: 생체 인증 [사용] 가능 [결과] 확인]")
print("결과 :: 사용 가능")
print("type :: ", biometricType(for: context.biometryType))
print("msg :: ", A_Auth.CHECK_SUCCESS)
print("====================================")
print("")
// MARK: [evaluate 사용 가능]
returnDic["result"] = true
returnDic["msg"] = A_Auth.CHECK_SUCCESS
// [세마포어 신호 알림]
semaphore.signal()
// [세마포어 확인 대기]
semaphore.wait()
// [리턴 데이터 반환]
return returnDic
}
// MARK: - [생체 인증 수행 >> 결과 확인 실시]
@available(iOS 11.0, *) // [특정 IOS 버전 이상 사용 가능]
func evaluate() {
print("")
print("====================================")
print("[A_Auth >> evaluate() :: 생체 인증 [수행] 실시]")
print("====================================")
print("")
self.context.evaluatePolicy(self.policy, localizedReason: self.localizedReason) { (success, error) in
if success == true {
print("")
print("====================================")
print("[A_Auth >> evaluate() :: 생체 인증 [결과] 확인 실시]")
print("결과 :: 생체 인증 성공")
print("msg :: ", A_Auth.CHECK_SUCCESS)
print("====================================")
print("")
// [노티피케이션 알림 전송 실시]
NotificationCenter.default.post(
name: NSNotification.Name(rawValue: A_Auth.NOTI_CHANNER), // 알림을 식별하는 태그
object: nil, // 발송자가 옵저버에게 보내려고 하는 객체
userInfo: ["message" : "\(A_Auth.CHECK_SUCCESS)"] // 객체의 저장소 [AnyHashable: Any] 형태
)
return
}
else {
print("")
print("====================================")
print("[A_Auth >> evaluate() :: 생체 인증 [결과] 확인 실시]")
print("결과 :: 에러 발생 확인")
print("error :: ", error?.localizedDescription ?? "")
print("retry :: ", self.biometricError(from: error as! NSError).0)
print("msg :: ", self.biometricError(from: error as! NSError).1)
print("====================================")
print("")
// MARK: [재실행 수행인 경우]
if self.biometricError(from: error as! NSError).0 == 1 {
// [다시 호출 수행 실시]
self.evaluate()
}
else {
// [노티피케이션 알림 전송 실시]
NotificationCenter.default.post(
name: NSNotification.Name(rawValue: A_Auth.NOTI_CHANNER), // 알림을 식별하는 태그
object: nil, // 발송자가 옵저버에게 보내려고 하는 객체
userInfo: ["message" : self.biometricError(from: error as! NSError).1 ?? ""] // 객체의 저장소 [AnyHashable: Any] 형태
)
}
return
}
}
}
// MARK: - [생체 인증 수행 실시]
@objc func simpleAuth(view: UIViewController){
print("")
print("====================================")
print("[A_Auth >> simpleAuth() : 생체 인증 수행 실시]")
print("====================================")
print("")
DispatchQueue.main.async {
// [생체 인증 클래스 객체 생성 실시]
let a_auth = A_Auth()
// [생체 인증 수행 실시]
if #available(iOS 11.0, *) { // MARK: [특정 ios 버전 이상 사용 가능]
// MARK: [생체 인증 사용 가능 여부 확인]
let canEvaluateDic : Dictionary<String, Any> = a_auth.canEvaluate()
print("")
print("====================================")
print("[A_Auth >> simpleAuth() :: 생체 인증 사용 여부 확인]")
print("결과 :: Face ID / Touch ID 사용 가능 여부 확인")
print("canEvaluateDic :: \(canEvaluateDic)")
print("====================================")
print("")
if (canEvaluateDic["result"] != nil) == true { // [생체 인증 사용 가능한 경우]
// MARK: [생체 인증 수행 실시]
a_auth.evaluate()
}
else { // [생체 인증 사용 불가능한 경우]
// [팝업창 알림 표시 수행 실시]
self.showAlert(
view: view,
tittle: "[생체 사용 가능 여부]",
content: "\(canEvaluateDic["msg"]!)",
okBtb: "확인",
noBtn: "취소"
)
}
} else {
print("")
print("====================================")
print("[ViewController >> simpleAuth() :: 생체 인증 사용 여부 확인]")
print("결과 :: IOS 버전 11 미만 >> 생체 인증 사용 제한 디바이스")
print("====================================")
print("")
}
}
}
// MARK: [alert 팝업창 호출 메소드 정의 실시 : 이벤트 호출 시]
// 호출 방법 : [[A_Auth shared] showAlertWithView:self tittle:@"[알 림]" content:msgData okBtb:@"확인" noBtn:@"취소"];
@objc func showAlert(view:UIViewController, tittle:String, content:String, okBtb:String, noBtn:String) {
DispatchQueue.main.async {
// [UIAlertController 객체 정의 실시]
let alert = UIAlertController(title: tittle, message: content, preferredStyle: UIAlertController.Style.alert)
// [인풋으로 들어온 확인 버튼이 nil 아닌 경우]
if(okBtb != "" && okBtb.count>0){
let okAction = UIAlertAction(title: okBtb, style: .default) { (action) in
// [확인 버튼 클릭 이벤트 내용 정의 실시]
return
}
alert.addAction(okAction) // 버튼 클릭 이벤트 객체 연결
}
// [인풋으로 들어온 취소 버튼이 nil 아닌 경우]
if(noBtn != "" && noBtn.count>0){
let noAction = UIAlertAction(title: noBtn, style: .default) { (action) in
// [취소 버튼 클릭 이벤트 내용 정의 실시]
return
}
alert.addAction(noAction) // 버튼 클릭 이벤트 객체 연결
}
// [alert 팝업창 활성 실시]
view.present(alert, animated: false, completion: nil)
}
}
} // [클래스 종료]
[결과 출력]
반응형
'Objective-C' 카테고리의 다른 글
Comments