-1

All, I created the following function:

func determineStatus() -> Bool {
    let status = ABAddressBookGetAuthorizationStatus()
    var ok = false
    switch status {
        case .NotDetermined:
            println("Asking for Grant")
            ABAddressBookRequestAccessWithCompletion(nil) {
                (granted:Bool, err:CFError!) in
                ok = granted
                println("Granted Status: \(granted)")
            }
        case .Authorized:
            println("Authorized")
            ok = true
        case .Restricted:
            println("Restricted")
            ok = false
        case .Denied:
            println("Denied")
            ok = false
    }
    if ok == true {
        println("Creating AB Instance")
        return self.createAddressBook()
    } else {
        self.adbk = nil
        println("Not Authorized")
        return false
    }

}

And I call it from within my Master - Detail View. The first time I call it the view appears before the alert window asking for authorization, and it's empty. I get in my console:

Asking for Grant Not Authorized And, after I authorize: Granted Status: true So the if ok == true part of determineStatus get executed before the ABAddressBookRequestAccessWithCompletion(nil) completes. The second time I run it I get the data displayed. How can I change determineStatus in order for the if ok == true statement to be executed after ABAddressBookRequestAccessWithCompletion(nil) finishes?

  • I tried introducing dispatch_async in my code but it seems the use of it is not yet clear to me – Roberto Negro May 05 '15 at 06:53
  • Don't pass `nil` to `ABAddressBookRequestAccessWithCompletion`, and use the completion handler like they say [in the documentation](https://developer.apple.com/library/ios/documentation/AddressBook/Reference/ABAddressBookRef_iPhoneOS/index.html#//apple_ref/c/func/ABAddressBookRequestAccessWithCompletion) – Eric Aya May 05 '15 at 07:04
  • Eric, could you please share with me an example? I'm still very basic in Swift... – Roberto Negro May 06 '15 at 12:19
  • Actually, no need for this handler. I've added an example in my answer. – Eric Aya May 06 '15 at 14:08

1 Answers1

0

I found a working solution here.

Credits go to @matt, I just copy/pasted his code and added a call to the class for this example:

class MyAddressBook {
    var adbk : ABAddressBook!

    func createAddressBook() -> Bool {
        if self.adbk != nil {
            return true
        }
        var err : Unmanaged<CFError>? = nil
        let adbk : ABAddressBook? = ABAddressBookCreateWithOptions(nil, &err).takeRetainedValue()
        if adbk == nil {
            println(err)
            self.adbk = nil
            return false
        }
        self.adbk = adbk
        return true
    }

    func determineStatus() -> Bool {
        let status = ABAddressBookGetAuthorizationStatus()
        switch status {
        case .Authorized:
            return self.createAddressBook()
        case .NotDetermined:
            var ok = false
            ABAddressBookRequestAccessWithCompletion(nil) {
                (granted:Bool, err:CFError!) in
                dispatch_async(dispatch_get_main_queue()) {
                    if granted {
                        ok = self.createAddressBook()
                    }
                }
            }
            if ok == true {
                return true
            }
            self.adbk = nil
            return false
        case .Restricted:
            self.adbk = nil
            return false
        case .Denied:
            self.adbk = nil
            return false
        }
    }

    func getContactNames() {
        if !self.determineStatus() {
            println("not authorized")
            return
        }
        let people = ABAddressBookCopyArrayOfAllPeople(adbk).takeRetainedValue() as NSArray as [ABRecord]
        for person in people {
            println(ABRecordCopyCompositeName(person).takeRetainedValue())
        }
    }
}

And elsewhere, likely in a controller (I've tested in viewDidLoad of a simple test app, it works well), do this:

let myABInstance = MyAddressBook()
let result = myABInstance.determineStatus()
println("Succeeded: \(result)")
myABInstance.getContactNames()

What I've got:

true
Kate Bell
Daniel Higgins Jr.
John Appleseed
Anna Haro
Hank M. Zakroff
David Taylor
Community
  • 1
  • 1
Eric Aya
  • 69,473
  • 35
  • 181
  • 253