2012年3月28日水曜日

連絡先(Address Book)を利用する方法


連絡先(Address Book)を利用するAPIが用意されています。

ABPeoplePickerNavigationControllerを利用することで連絡先の画面を自分のアプリ内で表示し、選択された人の情報を取得できます。

・プロジェクトにAddressBook.framework, AddressBookUI.frameworkを追加する。

・Address Bookを利用するクラス宣言にMFMailComposeViewControllerDelegateプロトコルを追加する。

#import <MessageUI/MFMailComposeViewController.h>
#import <AddressBookUI/AddressBookUI.h>

@interface MyViewController : UIViewController <MFMailComposeViewControllerDelegate, ABPeoplePickerNavigationControllerDelegate>
@end

#import <AddressBookUI/ABPeoplePickerNavigationController.h>
#import <AddressBook/ABPerson.h>

@implementation
{
    NSString *selectedMailAddr;

}

//連絡先表示
- (IBAction)showAddressBook:(id)sender
{
    selectedMailAddr = nil;
    ABPeoplePickerNavigationController *picker =
    [[ABPeoplePickerNavigationController alloc] init];
    picker.displayedProperties = @[@(kABPersonEmailProperty)];
    if ([picker respondsToSelector:@selector(setPredicateForEnablingPerson:)])
    {
        picker.predicateForEnablingPerson
            = [NSPredicate predicateWithFormat:@"emailAddresses.@count > 0"];
    }
    //picker.delegate = self; //この例では不要
    picker.peoplePickerDelegate = self;
    [self presentViewController:picker animated:YES completion:nil];
}

- (void)mailComposeController:(MFMailComposeViewController*)controller
          didFinishWithResult:(MFMailComposeResult)result
                        error:(NSError*)error
{
    //必要であればエラー処理
    //モーダルビュー解除
    [self dismissViewControllerAnimated:YES completion:nil];

}

//連絡先UIで行がタップされたときに呼ばれる。連絡先画面に留まらないときはNOを返す。
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
      shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
    [self setMailAddrWithPerson:person];
    return NO;
}

//これは呼ばれなかったが、念のため追加。
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
      shouldContinueAfterSelectingPerson:(ABRecordRef)person
                                property:(ABPropertyID)property
                              identifier:(ABMultiValueIdentifier)identifier
{
    [self setMailAddrWithPerson:person];
    return NO;
}

//iOS8 連絡先UIで行がタップされたときに呼ばれる。
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
                         didSelectPerson:(ABRecordRef)person
{
    [self setMailAddrWithPerson:person];
}

//iOS8 これは呼ばれなかったが、念のため追加。
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
                         didSelectPerson:(ABRecordRef)person
                                property:(ABPropertyID)property
                              identifier:(ABMultiValueIdentifier)identifier
{
    [self setMailAddrWithPerson:person];

}
- (void)setMailAddrWithPerson:(ABRecordRef)person
{
    ABMultiValueRef addrs = (ABMultiValueRef)ABRecordCopyValue(person, kABPersonEmailProperty);
    NSString *addr = nil;
    long addrCount = ABMultiValueGetCount(addrs);
    if (addrCount == 0) {
        // [NLUtil showAlert:NSLocalizedString(@"NoAddrsFound", nil)];
        //この場合にNOを返して元の画面に戻る。連絡先UIに留まる場合はYESを返す。
    } else if (addrCount > 1) {
        //メールアドレスが複数ある場合はUIActionSheetを使用してそのうちのひとつを選択する。
        UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"メールアドレス選択"
                                                                 delegate:self
                                                        cancelButtonTitle:@"キャンセル"
                                                   destructiveButtonTitle:nil
                                                        otherButtonTitles:nil];
        actionSheet.tag = 9;
        //複数のアドレスをUIActionSheetのボタンにセット。
        for(int i=0; i<addrCount; i++) {
            [actionSheet addButtonWithTitle:(__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(addrs, i)];
        }
        //モーダルビューを解除する。
        //iOS7ではAnimated:NOpeoplePickerを閉じないと
        //'Sheet can not be presented because the view is not in a window: "エラーが発生する。
        [self dismissViewControllerAnimated:NO completion:nil];
        //UIActionSheetを表示。
        [actionSheet showInView:self.view];
    } else {
        //アドレスがひとつだけのときはそれをメールアドレスのテキストフィールドにセットする。
        addr = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(addrs, 0);
        selectedMailAddr = [addr copy];
        //モーダルビューを解除する。
        //if ([NLUtil isOS6] || [NLUtil isOS7])
            [self dismissViewControllerAnimated:YES completion:nil];
        [self sendMail];
    }
}

//actionSheetタップ
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == actionSheet.cancelButtonIndex) return;
    selectedMailAddr = [actionSheet buttonTitleAtIndex:buttonIndex];
    [self sendMail];
}

#pragma mark - Mail送信

- (void)sendMail
{
    if (![MFMailComposeViewController canSendMail])
    {
        //showAlert: メール送信不可
        return;
    }
    if (!selectedMailAddr) return;
    
    MFMailComposeViewController *mailView = [[MFMailComposeViewController alloc] init];
    //メール送信後のメッセージを受け取るため、mailViewdelegateselfをセット。
    mailView.mailComposeDelegate = self;
    //アドレス、サブジェクト等の設定。
    [mailView setToRecipients:@[selectedMailAddr]];
    [mailView setSubject:[NSString stringWithFormat:@"テストメール"]];
    [mailView setMessageBody:@"テストメール" isHTML:NO];
    //MFMailComposeViewControllerをモーダルビューで表示。
    [self presentViewController:mailView animated:YES completion:NULL];
}

- (void)dealloc
{
    selectedMailAddr = nil;
}

@end

参照: iOS Address Bookプログラミングガイド
        Address Book Programming Guide for iOS

0 件のコメント: