38

今後のアプリのベータユーザーの中には、連絡先のリストに重複するレコードがたくさん含まれていると報告している人がいます。連絡先のカスタマイズされたテーブルビューのデータソースとしてからの結果を使用してABAddressBookCopyArrayOfAllPeopleいますが、結果がiPhoneの「連絡先」アプリとは異なることに戸惑います。

連絡先アプリを詳しく見ると、重複は「リンクされたカード」のエントリに由来しているようです。以下のスクリーンショットは少しわかりにくくなっていますが、右端の私のアプリでわかるように、「Celine」は2回表示されますが、左側の連絡先アプリでは「Celine」は1つだけです。その単一の連絡先の行をクリックすると、2つの「リンクされたカード」を含む「統一情報」カードが表示されます(中央に示されているように、1つのスクリーンショットに収まらないため、Celineの連絡先の詳細は使用しませんでした)

スクリーンショット

「リンクされたカード」に関する問題は、エンドユーザー向けのAppleのフォーラムかなり数のトピックがありますが、多くが404サポートページを指しているという事実を除けば、アプリのユーザーのすべての名簿を現実的に修正することはできません。むしろ、ユーザーを煩わせることなく、エレガントに扱いたいと思います。さらに悪いことに、WhatsAppは重複する連絡先を含む同じリストを表示しているため、この問題を抱えているのは私だけではないようです。

重複する連絡先の出所を明確にするために、私は配列のABAddressBookCopyArrayOfAllPeople戻り値について保存、キャッシュ、またはその他の方法で賢くしようとはしていません。したがって、重複するレコードはAPI呼び出しから直接取得されます。

これらのリンクされたカードを処理または検出して、重複するレコードが表示されないようにする方法を知っている人はいますか?AppleのContactsアプリはそれを行いますが、他の人たちもそうすることができますか?

更新:私はライブラリを作成し、それをCocoapodsに配置して、目前の問題を解決しました。以下の私の答えを参照してください

4

5 に答える 5

35

1つの方法は、デフォルトのアドレス帳ソースから連絡先のみを取得することです。

ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *people = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeopleInSource(addressBook, ABAddressBookCopyDefaultSource(addressBook));

しかし、それは足りないですよね?これは、デバイス上のアドレス帳を対象としていますが、Exchangeやその他の派手な同期アドレス帳にある可能性のある追加の連絡先は対象としていません。

だからここにあなたが探している解決策があります:

  1. ABRecord参照を反復処理します
  2. それぞれの「リンクされた参照」を取得します(を使用ABPersonCopyArrayOfAllLinkedPeople
  3. それらをNSSetにバンドルします(グループ化を一意に識別できるようにするため)
  4. そのNSSetを別のNSSetに追加します
  5. 利益?

これで、リンクされたABRecordオブジェクトのNSSetを含むNSSetができました。包括的なNSSetは、「連絡先」アプリの連絡先の数と同じ数になります。

コード例:

NSMutableSet *unifiedRecordsSet = [NSMutableSet set];

ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef records = ABAddressBookCopyArrayOfAllPeople(addressBook);
for (CFIndex i = 0; i < CFArrayGetCount(records); i++)
{
    NSMutableSet *contactSet = [NSMutableSet set];

    ABRecordRef record = CFArrayGetValueAtIndex(records, i);
    [contactSet addObject:(__bridge id)record];

    NSArray *linkedRecordsArray = (__bridge NSArray *)ABPersonCopyArrayOfAllLinkedPeople(record);
    [contactSet addObjectsFromArray:linkedRecordsArray];

    // Your own custom "unified record" class (or just an NSSet!)
    DAUnifiedRecord *unifiedRecord = [[DAUnifiedRecord alloc] initWithRecords:contactSet];

    [unifiedRecordsSet addObject:unifiedRecord];
    CFRelease(record);
}

CFRelease(records);
CFRelease(addressBook);

_unifiedRecords = [unifiedRecordsSet allObjects];
于 2012-07-14T01:43:47.640 に答える
8

私はしばらくの間、アプリで ABPersonCopyArrayOfAllLinkedPeople() を使用しています。残念ながら、私はそれが常に正しいことをするとは限らないことを発見しました。たとえば、同じ名前の 2 つの連絡先があり、一方には「isPerson」フラグが設定されていて、もう一方には設定されていない場合、上記の関数はそれらを「リンク済み」と見なしません。なぜこれが問題なのですか?Gmail (交換) ソースはこのブール値フラグをサポートしていないためです。false として保存しようとすると失敗し、保存した連絡先は、アプリの次の実行時に、iCload (CardDAV) に保存した連絡先からリンク解除されたものとして戻ってきます。

ソーシャル サービスでの同様の状況: Gmail はそれらをサポートしておらず、上記の関数は、Facebook アカウントを持っている場合と持っていない場合に、同じ名前の 2 つの連絡先を異なるものとして表示します。

2 つの連絡先レコードを 1 つの連絡先として表示する必要があるかどうかを判断するために、独自の名前とソース レコード ID のみのアルゴリズムに切り替えています。作業は増えますが、銀の裏地があります。ABPersonCopyArrayOfAllLinkedPeople() は非常に遅いです。

于 2012-10-07T04:28:46.940 に答える
5

@Daniel Amitay が提供したアプローチには非常に価値のあるナゲットが含まれていましたが、残念ながらコードを使用する準備ができていません。連絡先を適切に検索することは、私や多くのアプリにとって非常に重要です。そのため、これを正しく行うためにかなりの時間を費やしましたが、一方で、iOS 5 および 6 と互換性のあるアドレス帳へのアクセス (ブロックを介したユーザー アクセスの処理) の問題にも対処しました。 )。これは、ソースが正しく同期されていないためにリンクされた多くのカードと、新しく追加された Facebook 統合からのカードの両方を解決します。

私が作成したライブラリは、メモリ内 (オプションでディスク上) の Core Data ストアを使用して住所録レコード ID をキャッシュし、統合された住所録カードを返す簡単なバックグラウンド スレッド検索アルゴリズムを提供します。

ソースは、CocoaPodsポッドである私の github リポジトリで入手できます。

pod 'EEEUnifiedAddressBook'
于 2012-10-03T20:10:45.953 に答える
0

すべてのソースを取得しABAddressBookCopyArrayOfAllSources、デフォルトのものABAddressBookCopyDefaultSourceを最初の位置に移動してから、それらを繰り返し、ABAddressBookCopyArrayOfAllPeopleInSource以前にリンクされたものをスキップしてソースからすべての人を取得し、次にそれぞれのリンクされた人を取得していますABPersonCopyArrayOfAllLinkedPeople

于 2013-02-15T00:26:38.733 に答える