2014-07-20 4 views
13

내 코드가 Swift로 컴파일되지 않는 이유를 모르겠습니다.Swift로 주소록 연락처를 검색하는 방법은 무엇입니까?

나는이 목표 - C 코드로 변환하려고 :

CFErrorRef error = NULL; 
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error); 

    if (addressBook != nil) { 
    NSLog(@"Succesful."); 

    NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); 
} 

이 스위프트에 내 현재 연주입니다 :

var error:CFErrorRef 
var addressBook = ABAddressBookCreateWithOptions(nil, nil); 

if (addressBook != nil) { 
    println("Succesful."); 

    var allContacts:CFArrayRef = ABAddressBookCopyArrayOfAllPeople(addressBook); 
} 

하지만, 엑스 코드 보고서 :

'관리되지 않는 '는'CFArrayRef '로 변환 할 수 없습니다.

의견이 있으십니까?

답변

24

iOS 버전 9 이상을 타겟팅하는 경우 분명히 AddressBook 프레임 워크를 사용하지 말고 대신 Contacts 프레임 워크를 사용해야합니다.

그래서,

  1. 가져 오기 Contacts는 :

    import Contacts 
    
  2. 당신의 Info.plistNSContactsUsageDescription를 제공해야합니다.

  3. 그런 다음 연락처에 액세스 할 수 있습니다. 예 : 스위프트 3 :

    let status = CNContactStore.authorizationStatus(for: .contacts) 
    if status == .denied || status == .restricted { 
        presentSettingsActionSheet() 
        return 
    } 
    
    // open it 
    
    let store = CNContactStore() 
    store.requestAccess(for: .contacts) { granted, error in 
        guard granted else { 
         DispatchQueue.main.async { 
          self.presentSettingsActionSheet() 
         } 
         return 
        } 
    
        // get the contacts 
    
        var contacts = [CNContact]() 
        let request = CNContactFetchRequest(keysToFetch: [CNContactIdentifierKey as NSString, CNContactFormatter.descriptorForRequiredKeys(for: .fullName)]) 
        do { 
         try store.enumerateContacts(with: request) { contact, stop in 
          contacts.append(contact) 
         } 
        } catch { 
         print(error) 
        } 
    
        // do something with the contacts array (e.g. print the names) 
    
        let formatter = CNContactFormatter() 
        formatter.style = .fullName 
        for contact in contacts { 
         print(formatter.string(from: contact) ?? "???") 
        } 
    } 
    

    주소록 프레임 워크

    func presentSettingsActionSheet() { 
        let alert = UIAlertController(title: "Permission to Contacts", message: "This app needs access to contacts in order to ...", preferredStyle: .actionSheet) 
        alert.addAction(UIAlertAction(title: "Go to Settings", style: .default) { _ in 
         let url = URL(string: UIApplicationOpenSettingsURLString)! 
         UIApplication.shared.open(url) 
        }) 
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel)) 
        present(alert, animated: true) 
    } 
    

내 원래의 대답은 아래입니다.


관찰의 커플 :

  • 당신이 ABAddressBookCreateWithOptionserror 매개 변수를 사용하여 정의하려면

    Unmanaged<CFError>? 수 있습니다.

  • 오류가 발생하면 오류 개체 (takeRetainedValue을 수행하므로 누출이 발생하지 않음)를 살펴보십시오.

  • 주소록의 takeRetainedValue도 반드시 확인하여 누출되지 않도록하십시오.

  • 아마도 연락처를 잡아서는 안되지만 우선 권한을 요청해야합니다.

모두 함께 당신이 얻을 당기기 :

// make sure user hadn't previously denied access 

let status = ABAddressBookGetAuthorizationStatus() 
if status == .Denied || status == .Restricted { 
    // user previously denied, so tell them to fix that in settings 
    return 
} 

// open it 

var error: Unmanaged<CFError>? 
guard let addressBook: ABAddressBook? = ABAddressBookCreateWithOptions(nil, &error)?.takeRetainedValue() else { 
    print(error?.takeRetainedValue()) 
    return 
} 

// request permission to use it 

ABAddressBookRequestAccessWithCompletion(addressBook) { granted, error in 
    if !granted { 
     // warn the user that because they just denied permission, this functionality won't work 
     // also let them know that they have to fix this in settings 
     return 
    } 

    if let people = ABAddressBookCopyArrayOfAllPeople(addressBook)?.takeRetainedValue() as? NSArray { 
     // now do something with the array of people 
    } 
} 
+1

관리되지 않는 ? 꽤 좋은 팁 이었어. 나머지도 가져 주셔서 감사합니다. –

관련 문제