2014-07-20 19 views
13

Ich verstehe nicht, warum mein Code nicht mit Swift kompiliert.Wie Adressbuch Kontakte mit Swift abrufen?

Ich versuche, diese Objective-C-Code zu konvertieren:

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

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

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

Dies ist meine aktuelle Wiedergabe in Swift:

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

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

    var allContacts:CFArrayRef = ABAddressBookCopyArrayOfAllPeople(addressBook); 
} 

aber Xcode berichtet:

‚Unmanaged 'ist nicht in' CFArrayRef 'umwandelbar

Habt ihr eine Idee?

Antwort

24

Wenn Sie iOS Version 9 oder höher verwenden, sollten Sie das Framework AddressBook natürlich nicht verwenden und stattdessen stattdessen das Framework Contacts verwenden.

So

  1. Import Contacts:

    import Contacts 
    
  2. Achten Sie auf eine NSContactsUsageDescription in Ihrem Info.plist zu liefern.

  3. Dann können Sie dann auf Kontakte zugreifen. Z.B. in Swift 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) ?? "???") 
        } 
    } 
    

    Wo

    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) 
    } 
    

Meine ursprüngliche Antwort für Rahmen Addressbook ist unten.


Ein paar Beobachtungen:

  • Wenn Sie error Parameter von ABAddressBookCreateWithOptions verwenden möchten, definieren sie Unmanaged<CFError>? sein.

  • Wenn es fehlschlägt, werfen Sie einen Blick auf das Fehlerobjekt (doing takeRetainedValue, so dass Sie nicht leckt).

  • Stellen Sie sicher, takeRetainedValue des Adressbuchs auch, so dass Sie nicht leak.

  • Sie sollten wahrscheinlich nicht nur die Kontakte greifen, aber Sie sollten wahrscheinlich zuerst um Erlaubnis fragen.

ziehen, dass alles, was Sie zusammen bekommen:

// 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

Unmanaged ? war ein ziemlich guter Tipp. Danke für den Rest auch. –