iOS8.0以降でABAddressBookUIの実装でハマったのでメモ

　アドレス帳からメールアドレスを引っ張ってきたかったので、ABAddressBookとABAddressBookUIをimportして、デリゲートを設定したのにうまくいかず、かなりハマったのでメモ。

 iOS7.x.xまでは、下記のデリゲートメソッドが呼ばれていましたが、

```swift:ViewController.swift
// Personを選択したとき呼ばれる（iOS8.0以前）
func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, shouldContinueAfterSelectingPerson person: ABRecord!) -> Bool {
    let multi: ABMultiValueRef = ABRecordCopyValue(person, kABPersonEmailProperty).takeRetainedValue()
    // メールアドレスが2件以上ある場合、
    if ABMultiValueGetCount(multi) > 1 {
        peoplePicker.displayedProperties = [NSNumber(int: kABPersonEmailProperty)]
        println("Selected Person has multiple mail addresses.")
        return true
    } else if ABMultiValueGetCount(multi) == 1 {
        // メールアドレスが1件だけの場合、
        let email = ABMultiValueCopyValueAtIndex(multi, 0).takeRetainedValue() as! String
            
        _userDefaults.setValue(email, forKey: "MailAddress")
        _userDefaults.synchronize()
        println("(iOS7)Selected Email address is: \(email)")

        _controller.popViewControllerAnimated(false)
        self.dismissViewControllerAnimated(true, completion: nil)
            
        return false
    } else {
        return false
    }
}

// ABPeoplePickerNavigationControllerで1つのプロパティ（電話番号やメールアドレス等）を選択したとき、
// デフォルトの処理（電話をかける、新規メール作成画面に遷移する等）を行うかどうかを返す。trueを返すとデフォルトの動作。
func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, shouldContinueAfterSelectingPerson person: ABRecord!, property: ABPropertyID, identifier: ABMultiValueIdentifier) -> Bool {
    let multi: ABMultiValueRef = ABRecordCopyValue(person, kABPersonEmailProperty).takeRetainedValue()
    let index: CFIndex = ABMultiValueGetIndexForIdentifier(multi, identifier)
        
    let email = ABMultiValueCopyValueAtIndex(multi, index).takeRetainedValue() as! String
        
    _userDefaults.setValue(email, forKey: "MailAddress")
    _userDefaults.synchronize()
    println("(iOS7.x)Selected Email address is: \(email)")
        
    _controller.popViewControllerAnimated(false)
    self.dismissViewControllerAnimated(true, completion: nil)
        
    return false
}
```

　iOS8.0以降では同メソッドはdeprecatedとなっていて、その代わりに下記のデリゲートメソッドが呼ばれることになっています。

```swift:ViewController.swift
// 選択したとき呼ばれる（iOS8.0以上のとき）
// ABPeoplePickerNavigationControllerで1つの連絡先を選択したとき、
func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecord!) {
    let multi: ABMultiValueRef = ABRecordCopyValue(person, kABPersonEmailProperty).takeRetainedValue()
    // メールアドレスが2件以上ある場合、
    if ABMultiValueGetCount(multi) > 1 {
        peoplePicker.displayedProperties = [NSNumber(int: kABPersonEmailProperty)]
        println("Selected Person has multiple mail addresses.")
        return
    } else if ABMultiValueGetCount(multi) == 1 {
        // メールアドレスが1件だけの場合、
        let email = ABMultiValueCopyValueAtIndex(multi, 0).takeRetainedValue() as! String
            
        _userDefaults.setValue(email, forKey: "MailAddress")
        _userDefaults.synchronize()
        println("(iOS8)Selected Email address is: \(email)")
            
        _controller.popViewControllerAnimated(false)
        self.dismissViewControllerAnimated(true, completion: nil)
            
        return
    }
}

// 詳細画面から戻るときに呼ばれる（iOS8.0以降で呼ばれる）
func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecord!, property: ABPropertyID, identifier: ABMultiValueIdentifier) {
    let multi: ABMultiValueRef = ABRecordCopyValue(person, kABPersonEmailProperty).takeRetainedValue()
    let index: CFIndex = ABMultiValueGetIndexForIdentifier(multi, identifier)
        
    let email = ABMultiValueCopyValueAtIndex(multi, index).takeRetainedValue() as! String
        
    _userDefaults.setValue(email, forKey: "MailAddress")
    _userDefaults.synchronize()
    println("(iOS8.x)Selected Email address is: \(email)")

    _controller.popToRootViewControllerAnimated(false)
    self.dismissViewControllerAnimated(true, completion: nil)
}
```

　しかし、デリゲートの設定して、上記のメソッドを実装してもなぜか呼ばれませんでした。

　いろいろ検索して調べた結果、下記が参考になりました。
[Github:mattneub/Programming-iOS-Book-Examples
](https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch18p713addressBook/ch31p973addressBook/ViewController.swift)

```swift:ViewController.swift
let _controller = ABPeoplePickerNavigationController()
// iOS8.0以上の対応
if _controller.respondsToSelector(Selector("predicateForEnablingPerson")) {
    // メールアドレスがない人は表示しない
    _controller.predicateForEnablingPerson = NSPredicate(format: "emailAddresses.@count > 0")
    // true：選択した人をアプリに返す、false:選択した人の詳細を表示する（iOS8.0以上対応）
    _controller.predicateForSelectionOfPerson = NSPredicate(value: false)
    // true：選択したプロパティをアプリに返す、false:選択した人の詳細データでデフォルトアクションを実行する（iOS8.0以上対応）
    _controller.predicateForSelectionOfProperty = NSPredicate(value: true)
}
```

上記のように、
_controller.predicate~
で条件を設定しないとデリゲートメソッドが呼ばれません。

Referenceをちゃんと読めば分かるんでしょうけど、ハマりました。