Things take time

[SWIFT] 주소록에 저장된 데이터 불러오기 본문

iOS (기능)

[SWIFT] 주소록에 저장된 데이터 불러오기

겸손할 겸 2017. 6. 12. 14:44

[주소록]


스위프트를 이용하여 카카오톡 처럼 기본 SNS를 만들어 보려고하는데.. 하이브리드만 해본 나로서는 네이티브의 모든 기능을 사용할 줄 모르는 상황,

안드로이드라면 좀 더 익숙하겠지만 iOS는 이제 막 공부하는 시점이기 때문에 어렵다.


게다가 스위프트로는 레퍼런스 자체가 많이 없다. 물론 영어로는 많지만.. 그렇게 구글러로 열심히 한 결과 주소록에 대한 개념을 잡았다.

(레퍼런스로 사용할 포스팅좀 많았으면 좋겠다.. 스위프트가 어려운 언어는 아니지만 응용 단계로 가면, 참고할 사이트가 많이 없다.)



[Addressbook, Contacts]


주소록을 가져오기 위해서 import해야하는 라이브러리가 있는데 Addressbook은 iOS 9.0대부터 deprecated되었기 때문에 사용하면 안되고, Contacts를 사용하는 것이 맞다고 한다. 물론 8.0을 비롯한 하위 버전까지를 고려한다면 앱 실행 시, 코드를 분리시켜야할 것이다. 나는 Contacts만을 사용했다.

import Contacts

로직은 간단하다. 바로 연락처를 키는 것이 아니라..

사용자에게 연락처 접근 권한을 허용받고, 허용 받았을 때만 주소를 가져오며.. 허용하지 않았다면 사용자에게 허용하도록 설정창으로 이동시키는 작업까지



먼저 plist파일에 Contacts Usage Description을 추가하여 해당 권한에 접근하겠다 명시해야한다.

그리고 주소록 데이터를 저장하는 클래스 상수를 선언한다.

let store = CNContactStore()

CNContactStore라는 클래스는 주소록 데이터를 저장하고 있다. 이 외에도 특정 문자열(이름 등)을 주소록에서 검색하게 하는 CNContact.predicateForContactsMatchingName등.. 여러 클래스, 클래스 함수가 있으니 필요하면 검색해서 활용하면 된다.

// 주소록에서 얻어온 데이터들을 저장할 배열 var contacts = [CNContact]() // 주소록에서 가져올 데이터들의 타입, 이름, 폰번호 let keys = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName), CNContactPhoneNumbersKey as CNKeyDescriptor]

// 주소록에서 가져올 데이터들의 옵션을 저장하는 객체 let request = CNContactFetchRequest(keysToFetch: keys) store.requestAccess(for: .contacts, completionHandler: { (granted , err) in //권한 허용 시 if(granted){ do { try self.store.enumerateContacts(with: request) { (contact, stop) in // 이름은 있으나 폰 번호가 없는 경우 if !contact.phoneNumbers.isEmpty { contacts.append(contact) } } for info in contacts{ guard let phone = info.phoneNumbers[0].value.value(forKey: "digits") else { return } let name = info.familyName + info.givenName print(phone) print(name) } } catch { print("unable to fetch contacts") } } // 권한 비 허용 시 else { let toast = UIAlertController(title: "알림", message: "주소록 권한이 필요합니다.", preferredStyle: .alert) toast.addAction(UIAlertAction(title: "확인", style: .default, handler: { (Action) -> Void in let settingsURL = NSURL(string: UIApplicationOpenSettingsURLString)! as URL UIApplication.shared.open(settingsURL, options: [:], completionHandler: nil) })) self.present(toast, animated: true, completion: nil) } })

CNContactStore().requestAccess란 함수를 통해 유저가 주소록 접근을 허용했는지에 대한 값(granted)이 bool로 리턴되며 이에 대한 값에 대한 판별을 통해 연락처를 가져올 것인지.. 아니면 주소록 권한 요청과 함께 확인을 누르면 해당 앱 설정창으로 이동시키는지 분기처리를 했다.


주석으로 설명을 적었으니 어렵지는 않을 것이다. 참고로 이름은 있는데 번호가 없거나, 혹은 그 반대인 경우도 생각해야한다. (위 소스는 완성 소스가 아님) 없는 경우 어플이 죽어버리기때문에.. guard나 if let으로 해도 안되더라. 그냥 CNContactSotre().enumerateContacts에서 처리해야할 듯 하다.


물론 이 외에도.. 권한에 대한 리턴 값을 다른 방법으로 얻어올 수 있다.

        let abc = CNContactStore.authorizationStatus(for: CNEntityType.contacts)
        switch abc {
        case .authorized:
            print("authorized")
        case .denied:
            print("denied")
        case .notDetermined:
            print("notDetermined")
        case .restricted:
            print("restricted")
        }

위처럼 현재 상태에 대한 리턴값을 얻어올 수 있으므로.. 이에 따라 처리를 할 수도 있다. requestAccess란 함수로도 충분히 할 수 있어서 나 같은 경우에는 따로 하지 않았다.