Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RHAddressBook::people - Duplicate entries for linked contacts #33

Open
0xdevalias opened this issue Nov 8, 2013 · 3 comments
Open

RHAddressBook::people - Duplicate entries for linked contacts #33

0xdevalias opened this issue Nov 8, 2013 · 3 comments

Comments

@0xdevalias
Copy link

While playing around with RHAddressBook for an app i'm working on, I noticed that the people method in RHAddressBook.m will return duplicates if the contact exists in multiple sources. This seems to be a common issue, related to the underlying API.

Googling around, I came across this stackoverflow thread which seems to offer up a decent algorithm for a solution.

I think this would make a good addition to RHAddressBook. Something like this, but probably with better method names..

-(NSArray*)peopleWithoutLinkedDuplicates; // This would return an array of all users with 'linked duplicates' removed, returning the person from the default source for any duplicates (convenience method for below)

-(NSArray*)peopleWithoutLinkedDuplicatesShowingSource:(RHSource *)source; // This would return an array of all users with 'linked duplicates' removed, returning the person from the supplied source for any duplicates

I'd be happy to look at implementing this and sending a pull request if you'd like. Just let me know how you'd want the methods named, etc.

@heardrwt
Copy link
Owner

heardrwt commented Nov 8, 2013

Sounds like a good addition to have in the framework.

As for method names, perhaps:

-(NSArray*)unifiedPeople;
-(NSArray*)unifiedPeoplePreferringSource:(RHSource*)source;

or

-(NSArray*)peopleUnifiedUsingDefaultSource;
-(NSArray*)peopleUnifiedUsingSource:(RHSource*)source;

If you have some working code, feel free to post it or chuck it in a pull request.

@0xdevalias
Copy link
Author

I like the second one better :) Was also thinking it would probably be beneficial to be able to unify any array of RHPerson's (for example, returned from peopleOrderedByUsersPreference, etc)

Been hacking around with it a little this afternoon, and this is what I came up with. The first part (based on stackoverflow) is quite clean, but I'm not the happiest with my next part for picking the record we want out of the unified set (pretty sure it's overkill and too laggy)

-(NSArray *)unifyPeople:(NSArray *)people
            usingSource:(RHSource *)source
{
    // Ref: http://stackoverflow.com/questions/11351454/dealing-with-duplicate-contacts-due-to-linked-cards-in-ios-address-book-api

    int defaultSourceID = (int)source.addressBook.defaultSource.recordID;
    int wantedSourceID = (int)source.recordID;

    NSPredicate *recordIdMatchesDefault = [NSPredicate predicateWithFormat:@"%K = %d",
                                           @"inSource.recordID",
                                           defaultSourceID];
    NSPredicate *recordIdMatchesSource = [NSPredicate predicateWithFormat:@"%K = %d",
                                          @"inSource.recordID",
                                          wantedSourceID];

    NSMutableOrderedSet *unifiedPeopleSet = [NSMutableOrderedSet orderedSet];
    NSMutableOrderedSet *unifiedPeopleForSourceSet = [NSMutableOrderedSet orderedSet];

    // Create set of unified contacts
    for (RHPerson *person in people)
    {
        NSMutableSet *contactSet = [NSMutableSet set];

        [contactSet addObject:person];
        [contactSet addObjectsFromArray:person.linkedPeople];

        [unifiedPeopleSet addObject:contactSet];
    }

    // Filter the set for our desired source (or default)
    for (NSSet *contactSet in unifiedPeopleSet)
    {
        RHPerson *uniquePerson = nil;
        NSSet *wantedSet = [contactSet filteredSetUsingPredicate:recordIdMatchesSource];
        NSSet *defaultSet = [contactSet filteredSetUsingPredicate:recordIdMatchesDefault];

        if (wantedSet.count >= 1)
        {
            uniquePerson = wantedSet.anyObject;
        }
        else if (defaultSet.count >= 1)
        {
            uniquePerson = defaultSet.anyObject;
        }
        else
        {
            uniquePerson = contactSet.anyObject;
        }

        [unifiedPeopleForSourceSet addObject:uniquePerson];
    }

    return [unifiedPeopleForSourceSet array];
}

@nebiros
Copy link

nebiros commented Apr 22, 2015

Got the same issue, any resolution about this?.

nebiros added a commit to nebiros/RHAddressBook that referenced this issue Apr 23, 2015
unify duplicates records if the contact exists in multiple sources, see
http://stackoverflow.com/a/11480352/255463 and heardrwt#33.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants