0

In my app, I have list of contacts which are displayed in ascending order.When user clicks on any alphabet say 'b' then the list should scrolls to the contact starting from 'b'.Is this built-In functionality of AddressBook?Can anyone knows how I can achieve this?

Thanks in advance!

Nuzhat Zari
  • 3,398
  • 2
  • 24
  • 36
  • 1
    That is not a sort functionality... – Manlio Sep 20 '11 at 08:04
  • As far as I know, there isn't a way to do it without Jailbreaking. But - it doesn't really seem like it would be that hard to implement yourself either, it's definitely doable. – Jordan Smith Sep 20 '11 at 08:21

1 Answers1

1

My pretty dirty method. It sorts by email, first name and last name omitting middle name cause I didn't needed that one. Oh and it finds only those contacts which have email address. You can avoid that if you slightly edit code starting with if (ABMultiValueGetCount(emailRef))

Your view controller:

    - (NSArray *)sortedContactsFromPeople:(CFArrayRef)people {
  NSMutableArray *contacts = [NSMutableArray array];

  for (int i = 0; i < CFArrayGetCount(people); i++) {
    ABRecordRef record = CFArrayGetValueAtIndex(people, i);
    ABMultiValueRef emailRef = ABRecordCopyValue(record, kABPersonEmailProperty);
    CFStringRef email;

    if (ABMultiValueGetCount(emailRef)) {

      BOOL hasValidEmail = NO;

      for (int j = 0; j < ABMultiValueGetCount(emailRef); j++) {
        if (!hasValidEmail) {
          email = ABMultiValueCopyValueAtIndex(emailRef, j);
          if ([Validator validateEmail:(NSString *)email] == kValNoErr)
            hasValidEmail = YES;
          else
            CFRelease(email);
        }
      }

      if (hasValidEmail) {
        CFStringRef name = ABRecordCopyValue(record, kABPersonFirstNameProperty);        
        CFStringRef lastname = ABRecordCopyValue(record, kABPersonLastNameProperty);

        NSData *contactImageData = (NSData*)ABPersonCopyImageData(record);
        UIImage *img = [[[UIImage alloc] initWithData:contactImageData] autorelease];
        [contactImageData release];

        if (lastname == nil)
          lastname = (CFStringRef)@"";

        if (name == nil)
          name = (CFStringRef)@"";

        Contact *contact = [[[Contact alloc] initWithName:(NSString *)name
                                                 lastname:(NSString *)lastname
                                                    email:(NSString *)email
                                              profileIcon:img] autorelease];

        if (![(NSString *)lastname isEqualToString:@""])
          contact.sortChar = [(NSString *)lastname substringToIndex:1];
        else if (![(NSString *)name isEqualToString:@""])
          contact.sortChar = [(NSString *)name substringToIndex:1];
        else if (![(NSString *)email isEqualToString:@""])
          contact.sortChar = [(NSString *)email substringToIndex:1];                 

        contact.idNumber = ABRecordGetRecordID(record);

        [contacts addObject:contact];

        if (lastname)
          CFRelease(lastname);
        if (name)
          CFRelease(name);
        CFRelease(email);
      }
    }
    CFRelease(emailRef);
  }

  NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"sortChar" ascending:YES selector:@selector(caseInsensitiveCompare:)];
  [contacts sortUsingDescriptors:[NSArray arrayWithObject:descriptor]];
  return contacts;
}

- (void)initBaseValues {
  sections = [[NSMutableDictionary alloc] init];

  ABAddressBookRef addressBook = ABAddressBookCreate();

  CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);

  NSInteger section = 0;
  NSString *prevChar = nil;

  NSArray *contacts = [self sortedContactsFromPeople:people];

  for (int i = 0; i < contacts.count; i++) {

    Contact *contact = [contacts objectAtIndex:i];

    BOOL sectionExists = NO;

    if ([prevChar isEqualToString:contact.sortChar])
      sectionExists = YES;

    if (!sectionExists) {
       [sections setObject:[NSMutableArray array] forKey:[NSString stringWithFormat:@"%d", section]];
       section++;
    }

    [prevChar autorelease];
    prevChar = [contact.sortChar copy];

    [[sections objectForKey:[NSString stringWithFormat:@"%d", section-1]] addObject:contact];
  }

  if (prevChar != nil)
    [prevChar release];

  CFRelease(people);
  CFRelease(addressBook);
}

Contact.h

@interface Contact : NSObject {
  NSString *name;
  NSString *lastname;
  NSString *email;
  UIImage  *profileIcon;
  NSInteger idNumber;
}

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *lastname;
@property (nonatomic, copy) NSString *email;
@property (nonatomic, retain) UIImage *profileIcon;
@property (nonatomic) NSInteger idNumber;
@property (nonatomic, copy) NSString *sortChar;

- (id)initWithName:(NSString *)name_
          lastname:(NSString *)lastname_
             email:(NSString *)email_
       profileIcon:(UIImage *)profileIcon_;

@end

Doh! I wasn't vigilant enough, to read the whole thing carefully. :) Try creating NSMutableDictionary and each time headerForSection: method is being called store it's offset in the dictionary with appropriate letter as key. Then when user selects "B" letter send your UITableView setContentOffset:animated: method with appropriate offset taken from that dictionary.

Eugene
  • 10,006
  • 4
  • 37
  • 55
  • Hey thanks for the reply but from contacts I mean list of customer.I have an array which contains customer names, which I am displaying using simple UITableView. – Nuzhat Zari Sep 20 '11 at 11:07
  • Well the code above still does the sorting of any types of contacts you might need. See that you can remove all the code which uses ABAddressBook and achieve the same goal. As for the table view, return the "sections" dictionary count in 'numberOfSectionsInTableView:' and return '[sections objectForKey:[NSString stringWithFormat:@"%d", indexPath.row]];' in 'numberOfRowsInSection:'. – Eugene Sep 20 '11 at 12:22