アドレス帳からメールアドレスを引っ張ってきたかったので、ABAddressBookとABAddressBookUIをimportして、デリゲートを設定したのにうまくいかず、かなりハマったのでメモ。
iOS7.x.xまでは、下記のデリゲートメソッドが呼ばれていましたが、
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となっていて、その代わりに下記のデリゲートメソッドが呼ばれることになっています。
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
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をちゃんと読めば分かるんでしょうけど、ハマりました。