2012年12月10日月曜日

アドレスブック(連絡先)からの情報取得

アドレスブック(連絡先)へアクセスするには以下の様にします。


// アドレスブックを生成
ABAddressBookRef book = ABAddressBookCreateWithOptions(NULL, nil);
// アドレスブックのレコード配列を取得
CFArrayRef records = ABAddressBookCopyArrayOfAllPeople(book);

// 配列の要素の数だけ繰り返す
for (int i = 0 ; i < CFArrayGetCount(records) ; i++) {
    // 1レコード取得
    ABRecordRef record = CFArrayGetValueAtIndex(records, i);
    // 名を取得
    NSString *firstName = (NSString*)ABRecordCopyValue(record, kABPersonFirstNameProperty);
    if (firstName == nil) {
        firstName = @""; // 無ければ空文字に
    }
    // 氏を取得
    NSString *lastName = (NSString*)ABRecordCopyValue(record, kABPersonLastNameProperty);
    if (lastName == nil) {
        lastName = @""; // 無ければ空文字に
    }
    // 氏名を生成
    NSString *name = [NSString stringWithFormat:@"%@ %@", lastName, firstName];
    NSLog(@"%@", name);
    if (firstName != nil) {
        CFRelease(firstName);
    }
    if (lastName != nil) {
        CFRelease(lastName);
    }
    // レコードから電話番号の取得
    ABMultiValueRef tels = ABRecordCopyValue(record, kABPersonPhoneProperty);
    if (ABMultiValueGetCount(tels)) {
        NSString *tel = (NSString*)ABMultiValueCopyValueAtIndex(tels, 0);
        NSLog(@"%@", tel);
        CFRelease(tel);
    }
}
CFRelease(book);
CFRelease(records);


「ABRecordCopyValue」のパラメータで指定するkABPersonFirstNameProperty等で連絡先から何を取得するかを指定します。
その他プロパティには以下のものがあります。

kABPersonFirstNameファーストネーム
kABPersonLastNameラストネーム
kABPersonMiddleNameミドルネーム
kABPersonPrefixPropertyプレフィックス
kABPersonSuffixPropertyサフィックス
kABPersonNicknamePropertyニックネーム
kABPersonFirstNamePhoneticPropertyファーストネームの読み
kABPersonLastNamePhoneticPropertyラストネームの読み
kABPersonMiddleNamePhoneticPropertyミドルネームの読み
kABPersonOrganizationProperty組織
kABPersonJobTitleProperty役職
kABPersonDepartmentProperty部門
kABPersonDepartmentPropertyEメール
kABPersonBirthdayProperty誕生日
kABPersonNotePropertyメモ
kABPersonCreationDateProperty作成日
kABPersonModificationDateProperty更新日
kABPersonAddressProperty住所
kABPersonDateProperty日付
kABPersonKindProperty種別
kABPersonPhoneProperty電話番号
kABPersonInstantMessagePropertyインスタントメッセージ
kABPersonURLPropertyURL
kABPersonRelatedNamesProperty関係

また、アドレスブックから取得した各種情報はCFReleaseで解放する必要があります。(ARCを使用していない場合)


2012年7月6日金曜日

Apple Developer登録の更新方法

アップルのデベロッパー登録は、1年ごとに更新する必要があります。

毎年やる度に試行錯誤することになってしまうので、備忘録として記録しておきます。

各種証明書の概念はこちらの説明に譲るとして、以下の流れで各種証明書を更新する必要があります。



1. アプリケーション→ユーティリティにあるキーチェーンアクセス.appを起動し、「iPhone Developer」証明書と「iPhone Distribution」証明書を削除する。(ログインタブとシステムタブにあります。念のため削除後に検索バーから「iPhone」で検索をかけて旧い証明書が検索されないか確認する。旧いのが残っていると、後でビルド時に証明書関連のエラーが出て時間を浪費することになるので注意。)

2. 「キーチェーンアクセス」→「証明書アシスタント」→「認証局に証明書を要求」後、「ユーザーのメールアドレス」、「通称」を入力、(「CAのメールアドレス」は空でも良い)要求の処理に「ディスクに保存」をチェック、「鍵ペア情報を生成」はチェック無しで「続ける」をクリックし、「CertificateSigningRequest.certSigningRequest」証明書をデスクトップに書き出し。

3. アップルのデベロッパーサイトを開き、Certificatesから「Request Certificate」をクリック。


4. 画面下部の「ファイルを選択」をクリックする。


5. 2で書き出した証明書ファイルを選択し、「submit」ボタンをクリックする。

6. 証明書の「Status」が「Pending」になるので、他のタブ(Distribution等)を選択後、適当な時間待ってから「Development」タブを選択する。

7. 「Status」が「Issued」に変わり、「Download」ボタンが押せるようになっているので、クリックして証明書(ios_development.cer)をダウンロードする。


8. ダウンロードした証明書(ios_development.cer)ファイルをダブルクリックする。(キーチェーンアクセス.appで新しい有効期限の証明書になっていることを確認する。)

9. 「Distribution」タブをクリックし、「Revoke」をクリック。確認画面で「OK」を押して期限切れ間近(または既に期限切れになっている)Distribution用証明書を削除する。


10. 「Request Certificate」ボタンが押せるようになっているのでクリックする。


11. 「ファイルを選択」をクリックする。


12. 2で書き出したファイルを選択し、「submit」ボタンをクリックする。

13. 証明書の「Status」が「Pending」になるので、他のタブ(Development等)を選択後、適当な時間待ってから「Distribution」タブを選択する。

14. 「Status」が「Issued」に変わり、「Download」ボタンが押せるようになっているので、クリックして証明書(ios_distribution.cer)をダウンロードする。


15. ダウンロードした証明書(ios_distribution.cer)ファイルをダブルクリックする。(キーチェーンアクセス.appで新しい有効期限の証明書になっていることを確認する。)

16. 以上で終了です。App IDとDevice IDは変更する必要はありませんが、プロビジョニングプロファイルは再作成&ダウンロードする必要があります。



2012年6月4日月曜日

iOSアプリの証明書まとめ

iOSアプリを実機で動作させるには、iOS Developer Centerでいくつか証明書を作成・登録する必要があります。
以前、アップルのマニュアルなどを見て設定は行っているのですが、1年ごとの更新の度に忘れてしまうのでまとめておきます。

まずは概要からです。

以下、上の概要の手順を、1つずつ少し詳しく書いたものです。
まず、証明書署名要求ファイルの登録です。


次に、デバイスの登録です。

次に、アプリケーションの登録です。


次に、プロビジョニングプロファイルの登録です。



 最後に、ビルドします。



2012年1月20日金曜日

isaって何?

デバッグをしていると、よくisaという変数を目にすることがあります。
isaは、NSObjectが持っている構造体で、スーパークラスへのポインタや、メソッドの情報を保持しています。

例えば、NSMutableStringはNSStringクラスを継承したクラスですが、NSMutableStringのisa変数の中にNSStringへのポインタを保持しています。

また、NSMutableStringは「stringByAppendingString:」というメソッドを持っていますが、このメソッドの情報を以下の様にNSMutableStringのisa変数に格納しています。

セレクタ メソッド名の文字列
 22   stringByAppendingString:
 33   メソッドA
 44   メソッドB
 ・     ・
 ・     ・
 ・     ・

上の例のセレクタは説明の為適当な値です。また、セレクタはchar*型ですが、実際にはint型の数値が入ります。
Objective-Cのコンパイラは、メソッドの呼び出しを以下の様にC言語のコードに展開します。

[objA stringByAppendingString:objB];
  ↓
objc_msgSend(objA, 22, objB);

「objc_msgSend」関数は、objAにあるセレクタ22に対してobjBを送信してくれるC言語の関数です。
objc_msgSend関数はobjAの中にあるisa変数を参照して、指定されたセレクタ(22)を検索します。そしてそこにあったメソッドにobjBを渡すとともに呼び出してくれます。
ここで該当するセレクタがisaの中に見つからなかった場合は、スーパークラスであるNSStringのポインタを取得し、NSStringのisaに対して同様の処理を行います。
NSStringでも見つからなければ更にその継承元・・という風に辿っていき、最終的にNSObjectでも見つからなければ例外を発生させるという流れになります。

このような処理を行うことで、Objective-Cではプログラム実行時に動的にメソッドを入れ替えることがし易くなっているのです。

ただし、C言語のように直にポインタを呼び出すとかではないので動作は遅くなるはずです。また、C++言語と比べてもObjective-Cは検索処理などが行わる為、動作はかなり遅くなるはずです。(C++言語はクラスメソッドのジャンプテーブルを参照するのでC言語より数ステップ程度動作は遅くなります。)
多分ですが、メソッド呼び出しだけを見る限りC言語よりも数十倍〜数百倍は遅くなっているはずです。(遅さを補っても余りある利便性があるということです。)