Access contact image from address book based on name

一曲冷凌霜 提交于 2020-01-14 03:39:19

问题


Err,I have been pulling my hair thinking about a way from quite a few days.I have retrieved all contacts names and placed in an array using dictionary.

What I have is a model class holding a list of names,now I want to search the location of name in contacts list,depending on which I can retrieve the required contact image.

Initially googled and found out an unanswered question not pretty much similar to my requirement,the same can be glanced here

I tried several ways,the below is one way I have implemented:

EDIT

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    [self loadReminders];

    ReminderClass *reminderToDisplay = [self.remindersArray objectAtIndex:indexPath.row];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];

    // Now create the cell to display the reminder data
    if (cell == nil) 
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellIdentifier] autorelease];
        cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
        cell.textLabel.numberOfLines = 0;
        cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:17.0];
        cell.textLabel.adjustsFontSizeToFitWidth = YES;
    }

    tableView.backgroundColor = [UIColor clearColor];

    NSDateFormatter *dateFormat = [[[NSDateFormatter alloc]init]autorelease];
    [dateFormat setDateFormat:kDateFormat];
    NSDate *reminderDate = [dateFormat dateFromString:reminderToDisplay.Date]; 
    [dateFormat setDateFormat:kMinDateFormat]; 
    NSString *dateString = [dateFormat stringFromDate:reminderDate];

    NSString *valueString = [NSString stringWithFormat:@"%@'s %@",reminderToDisplay.Name,reminderToDisplay.Event];
    NSString *onString = [NSString stringWithFormat:@" on %@",dateString];
    NSString *reminderDetailsString = [valueString stringByAppendingString:onString];

    //Get the contact image based on name index from contact list
    ABAddressBookRef addressBook = ABAddressBookCreate( );
    CFStringRef reminderName = (CFStringRef)reminderToDisplay.Name;
    CFArrayRef allPeople = ABAddressBookCopyPeopleWithName(addressBook, reminderName);
    self.contactsList =[[[NSMutableArray alloc]init]autorelease];

    CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
    for ( int i = 0; i < nPeople; i++ ) 
    { 
    ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i); 
    NSString *contactFirstNamePart = (NSString *)ABRecordCopyValue(ref,kABPersonFirstNameProperty);
    NSString *contactFirstName = [[[NSString alloc] initWithString:contactFirstNamePart]autorelease];
    NSString *contactLastNamePart = (NSString *)ABRecordCopyValue(ref, kABPersonLastNameProperty);

    if (contactLastNamePart == nil)
    {
        self.contactName = contactFirstName;
    }

    else
    {
        NSString *contactLastName = [[[NSString alloc] initWithString:contactLastNamePart]autorelease];
        NSString *contactLastNameString = [NSString stringWithFormat:@" %@",contactLastName]; 
        self.contactName = [contactFirstName stringByAppendingString:contactLastNameString]; 
        CFRelease(contactLastNamePart);
    }

    NSDictionary *contactsDictionary = [NSDictionary dictionaryWithObjectsAndKeys:self.contactName, kContactName, [NSNumber numberWithInt:i], kContactIndex, nil];
    [self.contactsList addObject:contactsDictionary];
    CFRelease(contactFirstNamePart);
}

NSDictionary *contactsDictionary = [self.contactsList objectAtIndex:indexPath.row]; 
self.contactName = [contactsDictionary objectForKey:kContactName]; 
int addressIndex = [[contactsDictionary objectForKey:kContactIndex]integerValue];

ABRecordRef recordReference = CFArrayGetValueAtIndex(allPeople, addressIndex);
if (ABPersonHasImageData(recordReference))
{
    NSData *imageData = (NSData *)ABPersonCopyImageData(recordReference);
    self.reminderImage = [UIImage imageWithData:imageData];
    CFRelease(imageData);
}

CFRelease(allPeople);
CFRelease(addressBook);

    UIImage *notificationImage = reminderImage;

    if (notificationImage != nil) 
    {
        UIImageView *imageView=[[[UIImageView alloc] initWithFrame:CGRectMake(240, 3, 70, 63)]autorelease];
        imageView.backgroundColor=[UIColor clearColor];
        [imageView setImage:notificationImage];
        cell.accessoryView = imageView;
    }
    else
    {
        UIImageView *imageView=[[[UIImageView alloc] initWithFrame:CGRectMake(240, 3, 70, 63)]autorelease];
        imageView.backgroundColor=[UIColor clearColor];
        UIImage *defaultImage = [UIImage imageNamed:kDefaultImage];
        [imageView setImage:defaultImage];
        cell.accessoryView = imageView;
    }
    cell.textLabel.text = reminderDetailsString;
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    return cell;
}

Bad Access Error Screen shot

But I was unable to accomplish the required task.Can any one please guide me.

Thanks all in advance :)


回答1:


I am sharing the sample code snippet I used in one of my recent app. I have modified to fit it ur requirements and also please note that I have edited this in notepad and may have some typo errors.(Currently I dnt have mac to test it..:P) Basic idea is to fill the datasource in viewDidLoad method and use that dataSource to update the tableView. Hope this will be an input to solve your problem.

viewDidLoad

contactsToBeAdded=[[NSMutableArray alloc] init];
ABAddressBookRef addressbook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressbook);
CFIndex numPeople = ABAddressBookGetPersonCount(addressbook);
bool hasPhoneNumber = false;
for (int i=0; i < numPeople; i++) {
    hasPhoneNumber = false;
    ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
    ABMutableMultiValueRef phonelist = ABRecordCopyValue(person, kABPersonPhoneProperty);
    CFIndex numPhones = ABMultiValueGetCount(phonelist);


    if(numPhones > 0){
        hasPhoneNumber = true;

    }
    if(hasPhoneNumber){
        NSString *firstName=(NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
        NSString *lastName=(NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);

        CFTypeRef ABphone = ABMultiValueCopyValueAtIndex(phonelist, 0);
        NSString *personPhone = (NSString *)ABphone;

        NSMutableDictionary *dictToAdd = [[[NSMutableDictionary alloc]init]autorelease];
        if(firstName != nil && firstName != NULL){
            [dictToAdd setObject:firstName forKey:@"firstName"];
            CFRelease(firstName);
        }
        else{
            [dictToAdd setObject:@"" forKey:@"firstName"];
        }
        if(lastName != nil && lastName != NULL){
            [dictToAdd setObject:lastName forKey:@"lastName"];
            CFRelease(lastName);
        }
        else{
            [dictToAdd setObject:@"" forKey:@"lastName"];
        }

        if(personPhone != nil && personPhone != NULL){
            [dictToAdd setObject:personPhone forKey:@"mobile"];
            CFRelease(ABphone);
        }
        else{
            [dictToAdd setObject:@"" forKey:@"mobile"];
        }

        //Get the first name and last name added to dict and combine it to full name
        NSString *firstName = [dictToAdd objectForKey:@"firstName"];
        NSString *lastName = [dictToAdd objectForKey:@"lastName"];
        NSString *fullName = [firstName stringByAppendingString:lastName]; 

        //Now check whether the full name is same as your reminderToDisplay.Name
        if(reminderToDisplay.Name isEqualToString:fullName )
        {
            CFDataRef imageData = ABPersonCopyImageData(person);
            UIImage *image = [UIImage imageWithData:(NSData *)imageData];
            if(image != nil && image != NULL){
                [dictToAdd setObject:image forKey:@"image"];
                CFRelease(imageData);
            }
            else{
                [dictToAdd setObject:[UIImage imageNamed:TEMP_IMG] forKey:@"image"];
            }
        }

        [contactsToBeAdded addObject:dictToAdd];
    }

    CFRelease(phonelist);
}
CFRelease(allPeople);
CFRelease(addressbook);

[self.tableView reloadData];

numberOfRowsInSection

return contactsToBeAdded.count;

cellForRowAtIndexPath

static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil)
{
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]autorelease];

}

NSDictionary *contactToAdd;
//This way you can get the data added in viewDidLoad method
contactToAdd = [contactsToBeAdded objectAtIndex:indexPath.row];

NSString *fName = (NSString *)[contactToAdd objectForKey:@"firstName"];
NSString *lName = (NSString *)[contactToAdd objectForKey:@"lastName"];
UIImage *contactImg = (UIImage*)[contactToAdd objectForKey:@"image"];



回答2:


when you use 'ABAddressBookCopyArrayOfAllPeople' you get an array of persons in the addressbook. I believe they are type of ABPerson.

You can now loop over them list like you are. For each one record call 'ABPersonCopyImageData' and that will give you the image data as a CFDataRef.

And remember CFDataRef is a tool free bridge to NSData.




回答3:


Just try changing your code like this. You are adding dictionary items to ur contactsList, so get each dictionary and check whether it contains a key matching your reminderToDisplay.Name, if yes then do ur stuff..

for (NSDictionary* dict in contactsList)
{
   if(nil != [dict objectForKey:reminderToDisplay.Name])
   {
     //take image here
   }
}

UPDATE:

//This is the reminder's name you want to get contact image
ReminderClass *reminderToDisplay = [self.remindersArray objectAtIndex:indexPath.row];

 //Here you are adding your contacts with full name as object and kName as key, but check ur kName here
 NSDictionary *contactsDictionary = [NSDictionary dictionaryWithObjectsAndKeys:self.contactName, kName, [NSNumber numberWithInt:i], kIndex, nil]; 
 [self.contactsList addObject:contactsDictionary];

 //I dont think this part is needed in ur code
 NSDictionary *contactsDictionary = [self.contactsList objectAtIndex:indexPath.row]; 
 self.contactName = [contactsDictionary objectForKey:kName]; 
 int addressIndex = [[contactsDictionary objectForKey:kIndex]intValue];

Now you have your contact names as a dictionary in contactsList array, iterate the array and check whether the dictionary contains your reminderToDisplay.Name as key.

for (NSDictionary* dict in contactsList)
{
    //Please note that your dict contains key as kName and object as contact name.
    if(nil != [dict objectForKey:reminderToDisplay.Name])
    {
    }
}

Also, I feel like you can do this in one single loop, like when you are iterating the addressbook itself, you can check whether the contact name is in your reminderlist and if available then extract image.

Hope this helps..all the best...



来源:https://stackoverflow.com/questions/15138946/access-contact-image-from-address-book-based-on-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!