3

私のアプリでは、ユーザーの連絡先の特定のプロパティを取得する必要があります。たとえば、連絡先の名、姓、ミドル ネーム、ニックネーム、組織、役職、部署、誕生日、電子メールなどを取得する必要があります。それらはすべて非常に似ています。これは、機能しているメソッド (名) と機能していないメソッド (役職) のコードです。

+(NSString *)fetchFirstnameForPersonID: (NSUInteger)identifier{

    NSString *firstName;
    ABRecordRef currentPerson = (__bridge ABRecordRef)[[PSAddressBook arrayOfContacts] objectAtIndex:identifier];

    //If the first name property exists
    if ((__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonFirstNameProperty) != NULL){
    
        firstName = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonFirstNameProperty);        
    }    
    //If the first name property does not exist
    else{
        firstName = @"NULL";
    }
    return firstName;    
}

+(NSString *)fetchJobTitleForPersonID: (NSUInteger)identifier{

    NSString *jobTitle;
    ABRecordRef currentPerson = (__bridge ABRecordRef)[[PSAddressBook arrayOfContacts] objectAtIndex:identifier];

    if ((__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonJobTitleProperty) != NULL){
    
        jobTitle = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonJobTitleProperty);        
    }    
    else{
    
        jobTitle = @"NULL";
    }
    return jobTitle;    
}

arrayOfContacts次のように定義されたクラス メソッドです。

+(NSArray *)arrayOfContacts{

    //Creates an ABAddressBookRef instance containing the data from the address book database
    ABAddressBookRef addressBook = ABAddressBookCreate();

    //Creates an NSArray from the CFArrayRef using toll-free bridging
    NSArray *arrayOfPeople = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);

    CFRelease(addressBook);

    return arrayOfPeople;
}

これらのメソッドは、「PSPropertyFetcher」というモデル クラスで定義されています。ルート ビュー コントローラーで、いくつかの NSLog ステートメントを viewDidLoad に配置して、プロパティ フェッチャー メソッドが適切に機能しているかどうかを確認しました。テスト用のコードは次のとおりです。

NSLog(@"Property Fetchers Test\n");

for(NSUInteger i = 0; i <= ([PSAddressBook contactsCount]-1); i++){

    NSLog(@"First Name: %@", [PSPropertyFetcher fetchFirstnameForPersonID:i]);
    NSLog(@"Middle Name: %@", [PSPropertyFetcher fetchMiddlenameForPersonID:i]);
    NSLog(@"Last Name: %@", [PSPropertyFetcher fetchLastnameForPersonID:i]);
    NSLog(@"Organization: %@", [PSPropertyFetcher fetchOrganizationForPersonID:i]);
    NSLog(@"Department: %@", [PSPropertyFetcher fetchDepartmentForPersonID:i]);        
    NSLog(@"Job Title: %@\n\n", [PSPropertyFetcher fetchJobTitleForPersonID:i]);        
}

これは部分的にしか機能しません。これは出力です:

2012-06-27 10:37:30.094 Guess Who![80103:f803] プロパティ フェッチャー テスト

2012-06-27 10:37:30.108 Guess Who![80103:f803] 名: Jod

2012-06-27 10:37:30.114 Guess Who![80103:f803] ミドルネーム: ボブ

2012-06-27 10:37:30.118 Guess Who![80103:f803] 姓: サトソン

2012-06-27 10:37:30.122 Guess Who![80103:f803] 組織: ジョンソン アンド ジョンソン

2012-06-27 10:37:30.125 ゲス・フー![80103:f803] 部門: NULL

2012-06-27 10:37:30.128 Guess Who![80103:f803] 役職: NULL


2012-06-27 10:37:30.136 Guess Who![80103:f803] 名: Shemairan

2012-06-27 10:37:30.166 Guess Who![80103:f803] ミドルネーム: Daitran

2012-06-27 10:37:30.179 Guess Who![80103:f803] 姓: Catairan

2012-06-27 10:37:30.184 Guess Who![80103:f803] 組織: Shmairo and Co.

2012-06-27 10:37:30.188 Guess Who![80103:f803] 部門: NULL

2012-06-27 10:37:30.193 Guess Who![80103:f803] 役職: NULL


2012-06-27 10:37:30.202 Guess Who![80103:f803] 名: アレックス

2012-06-27 10:37:30.207 Guess Who![80103:f803] ミドルネーム: ジョン

2012-06-27 10:37:30.213 Guess Who![80103:f803] 姓: コーン

2012-06-27 10:37:30.219 Guess Who![80103:f803] 組織: Apple

2012-06-27 10:37:30.225 ゲス・フー![80103:f803] 部門: NULL

2012-06-27 10:37:30.230 Guess Who![80103:f803] 役職: NULL

iOS シミュレーターの連絡先アプリケーションで、各連絡先のすべてのフィールドに入力するようにしましたが、何らかの理由で「部門」と「役職」フィールドが正しく印刷されません。

基本的に、「役職」と「部門」のフェッチャー メソッドの何が問題なのか疑問に思っています。

前もって感謝します!

4

4 に答える 4

6

名簿のこのような小さなサンプリングではありそうにないようですが、ここではメモリリークが発生し、問題が発生する可能性があります。

arrayOfContactsを決定するために使用していると仮定すると[self contactsCount]、これらのクラスメソッドのすべてのループで毎回2つのAddressBookアイテムがリークすることになります。

この小さなサンプルでは、​​contactsWithJobTitlePropertyを開始するまでに、48個のAddressBookのみがリークされています。しかし、はるかに大きなAddressBookでこれらの値を繰り返し決定しようとしているより大きな例からこれを引き出した場合、何百ものぶら下がっているAddressBookオブジェクトがぶら下がっている可能性があります。

次のスニペットのようにCFReleaseを追加し、それが役立つかどうかを確認します。

+(NSArray *)arrayOfContacts{

    //Creates an ABAddressBookRef instance containing the data from the address book database
    ABAddressBookRef addressBook = ABAddressBookCreate();

    //Creates an NSArray from the CFArrayRef using toll-free bridging
    NSArray *arrayOfPeople = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
    CFRelease(addressBook);

    return arrayOfPeople;
}

(fwiw、プログラムをクラッシュさせる別のことは、ループカウンタータイプとしてNSUIntegerを使用していることですが、潜在的に-1になる可能性のある値に対してテストします...そして0はNSUIntegerのフロアであるため、アドレスが本には連絡先がありません。これは失敗しますが、それがこのクラッシュが発生している理由ではありません。)

于 2012-06-26T21:58:46.940 に答える
2

NULL 値にアクセスしているように見えますが、ブリッジ転送を実行する前に NULL かどうかをテストしてみましたか?

于 2012-06-26T08:28:31.870 に答える
1

これはあなたの問題を解決しないかもしれませんが、私があなただったら、いくつかの調整を行います:

+(NSUInteger)contactsWithJobTitleProperty{
    NSUInteger contactNumber = 0;
    // don't call arrayOfContacts in the loop -- 
    // when you do this you are creating a new address book 
    // each time the loop executes
    NSArray *contacts = [self arrayOfContacts];
    for(NSUInteger increment = 0; increment <= (contacts.count-1); increment++){
        ABRecordRef currentPerson = (__bridge ABRecordRef)[contacts objectAtIndex:increment];
        NSString *valueTest = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonJobTitleProperty);

        if(valueTest != NULL) {
            contactNumber++;
        }
    }
    return contactNumber;
}

また、@ john.k.doeが言及しましたが、必ずメソッドで使用CFRelease(addressBook);してくださいarrayOfContacts

于 2012-06-27T07:53:45.913 に答える