iPhone - View like SMS Contacts view - iphone

I'm trying to implement a view similar to contacts view in iPhone Message (SMS) app.
When composing a message on iPhone, there will be "+" button to add contacts. On click of "+", it will show list of contacts and just by selecting a contact, it will add the contact name in "To" text field.
I found following code to show contacts. But on click of a contact, its showing more details about the contact and just not selected.
ABPeoplePickerNavigationController* picker;
picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
CGRect newFrame = picker.view.frame;
newFrame.size.height = newFrame.size.height - 49;
picker.view.frame = newFrame;
[self presentModalViewController:picker animated:NO];
[picker release];
Can some body point out me correct way to select a contact?

I found the solution.
I've to implement the delegate methods to handle that.
The following are the delegate methods
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker {
[self dismissModalViewControllerAnimated:YES];
}
- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
.
.
.
.
[self dismissModalViewControllerAnimated:YES];
return NO;
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
return NO;
}

Related

Presenting MFMessageComposeViewController as soon as the user selects a contact from ABPeoplePickerNavigationController

Im working on an app which allows the user to select a contact from phone's address book and displays that contact in the UITableView. Im using following code to pick up the contact;
-(IBAction)pickPhoneContacts:(id)sender //opens phone's address book
{
ABPeoplePickerNavigationController *picker =
[[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
[self presentViewController:picker animated:YES completion:nil];
}
//called when user presses the cancel button in the Address book view controller
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController*)peoplePicker
{
[self dismissViewControllerAnimated:YES completion:nil];
}
//called when user pics up a contact from the phone's address book
- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person {
[self displayPerson:person]; //calls displayPerson:(ABRecordRef)person to show contact's information in the app
[self dismissViewControllerAnimated:YES completion:NULL];
return NO;
}
//called when the user selects the property of the contact. This method will not be called in the app but included to complete the implementation of the protocol
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)
peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
return NO;
}
//Displays the contact name and the contact's primary number in the app's text fields (add contact view controller)
- (void)displayPerson:(ABRecordRef)person
{
NSString* name = (__bridge_transferNSString*)ABRecordCopyValue(person,kABPersonFirstNameProperty); //Extracts the contact's first name from address book & assigns it to a string value
self.contactNameTextFiled.text = name;
NSString* phone = nil;
//Extracts the first phone number among multiple contact numbers from address book & assigns it to a string value
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person,kABPersonPhoneProperty);
if (ABMultiValueGetCount(phoneNumbers) > 0)
{
phone = (__bridge_transfer NSString*)
ABMultiValueCopyValueAtIndex(phoneNumbers, 0);
}
else
{
phone = #"[None]";
}
self.primaryNumberTextField.text = phone;
CFRelease(phoneNumbers);
}
Now the task is, as soon as the user pics up a contact from the address book, the ABPeoplePickerNavigator should dismiss and immediately MFMessageComposeViewController should present with a default message and the picked contact number. So that the user of the app should send a message to the picked contact number. I have used following code for message compose view controller;
-(void)sendSMS
{
MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
if([MFMessageComposeViewController canSendText])
{
controller.body = #"Test Message";
controller.recipients = [NSArray arrayWithObjects:#"111222333", nil];
controller.messageComposeDelegate = self;
[self presentViewController:controller animated:YES completion:nil];
}
}
Now please help me where should I call this method so that the MFMessageComposeViewController should present as soon as the ABPeoplePickerNavigationController dismiss.
Use new function dismissViewControllerAnimated: completion: so after completion call send sms as i have edited your code.
- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person {
[self displayPerson:person]; //calls displayPerson:(ABRecordRef)person to show contact's information in the app
// [self dismissViewControllerAnimated:YES completion:NULL];
[self dismissViewControllerAnimated:YES completion:^{
[self sendSMS];
}];
return NO;
}
Set animation of your adresscontroller to No when you are dismissing it
[self dismissViewControllerAnimated:NO completion:nil];
Try in
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person;
call
-(void)sendSMS
in dismissViewControllerAnimated:completion: completion handler.
[self dismissViewControllerAnimated:YES completion:{[self sendSMS]}];
Hopes this helps.
in .h file
MFMessageComposeViewController *controller ;
ABPeoplePickerNavigationController *picker;
and in .m just do this
in -(void)sendSMS
{
//other code
[picker presentViewController:controller animated:YES completion:nil];
}

Can not Edit Address Book Record from iphone app

I want to edit record from address book in my iphone app. But I can not edit any record. Here is my code
// In my First View Controller
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *detailViewController=[[DetailViewController alloc] initWithRecordObject:record];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
//------------------------------------
#import <UIKit/UIKit.h>
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
#import "User.h"
#interface DetailViewController : UIViewController <UITableViewDelegate,UITableViewDataSource,UIActionSheetDelegate,ABPersonViewControllerDelegate> {
ABRecordRef record;
// Some other ivars
}
- (id)initWithRecordObject:(ABRecordRef)myrecord;
//------------------------------------
#implementation DetailViewController
- (id)initWithRecordObject:(ABRecordRef)myrecord
{
self = [super initWithNibName:#"DetailViewController" bundle:nil];
if (self) {
record = myrecord;
}
return self;
}
#pragma mark - Edit Record Method
-(void)btnEditContactTapped:(id)sender {
// Fetch the address book
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordID recID = ABRecordGetRecordID(record);
ABRecordRef record1 = ABAddressBookGetPersonWithRecordID(addressBook,recID);
ABPersonViewController *personViewController = [[ABPersonViewController alloc]init];
// set delegate
personViewController.personViewDelegate = self;
// Allow editing info
personViewController.allowsEditing = YES;
// Display contact info of selected person
personViewController.displayedPerson = record1;
personViewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(returnFromPersonView)] ;
APP_DELGATE.isContactEdited = YES;
[self.navigationController pushViewController:personViewController animated:YES];
[personViewController release];
}
-(void)returnFromPersonView {
NSLog(#"In %s",__PRETTY_FUNCTION__);
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - ABPersonViewControllerDelegate Method
- (BOOL)personViewController:(ABPersonViewController *)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue {
//[self dismissModalViewControllerAnimated:YES];
return NO;
}
When I push personViewController , I can't see anything regarding record. Here is a screenshot
Any kind of help is highly appreciated.Thanks
Take a look at Apple's Adress Book Programming Guide. A page that would be useful to you is the Direct Interaction: Programmatically Accessing the Database page. I advise you to just look around at those pages, they are quite self explanatory.
Changing return to YES may help in last method
- (BOOL)personViewController:(ABPersonViewController *)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue {
//[self dismissModalViewControllerAnimated:YES];
return NO; //try changing it to YES
}
You are not passing the "Correct Contact ID" as ABRecordRef ;)

Cannot dismiss ABPersonViewController in iPhone

How can I dismiss the ABPersonViewController? Here is my code
#pragma mark - Edit Record Method
-(void)btnEditContactTapped:(id)sender {
// Fetch the address book
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordID recID = ABRecordGetRecordID(record);
ABRecordRef record1 = ABAddressBookGetPersonWithRecordID(addressBook,recID);
ABPersonViewController *personViewController = [[ABPersonViewController alloc]init];
// set delegate
personViewController.personViewDelegate = self;
// Allow editing info
personViewController.allowsEditing = YES;
// Display contact info of selected person
personViewController.displayedPerson = record1;
// Person view controllers must be used with a navigation controller in order to function properly.
UINavigationController *nc = [[UINavigationController alloc]
initWithRootViewController:personViewController];
[self presentModalViewController:nc animated:YES];
[personViewController release];
}
#pragma mark - ABPersonViewControllerDelegate Method
- (BOOL)personViewController:(ABPersonViewController *)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue {
[self dismissModalViewControllerAnimated:YES];
return NO;
}
record in my ivar declared as ABRecordRef record in .h file.
ABPersonViewControllerDelegate method never gets called? What's going wrong? Any kind of help is appreciated. Thanks
Have you implemented thesse protocols in .h of your project.. ?
< ABPeoplePickerNavigationControllerDelegate,
ABPersonViewControllerDelegate,
ABNewPersonViewControllerDelegate,
ABUnknownPersonViewControllerDelegate>

iPhone ABPeoplePickerNavigationController - How to select two single entries of two different multivalue properties of a person from Addressbook

I'm near desperation as I search for a solution for weeks now.
The Problem is simple:
Via the ABPeoplePickerNavigationController (as a ModalView), a person should be selected.
Then only (e.g.) the Mail addresses should be shown and the user should select one.
After selection of a Mail address just the (e.g.) phone numbers should be shown and the user should select one.
The solution until the third aspect is well-known:
- (IBAction)importFromAddressBook
{
ABPeoplePickerNavigationController* picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
[self presentModalViewController:picker animated:YES];
[picker release];
}
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
[self dismissModalViewControllerAnimated:YES];
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
[peoplePicker setDisplayedProperties:[NSArray arrayWithObject:[NSNumber numberWithInt:kABPersonEmailProperty]]];
return YES;
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier
{
//===PROBLEM=== Now I do have a mail address and I want to have a phone number right afterwards.
//Something like this would be straightforward, but the view does not change this way:
[peoplePicker setDisplayedProperties:[NSArray arrayWithObject:[NSNumber numberWithInt:kABPersonPhoneProperty]]];
//Here misses the important code.
//And only when I also got a phone number through this or a similar method I want to call:
[peoplePicker dismissModalViewControllerAnimated:YES];
//I do not want to start default behaviour with the mailaddress and/or phone number:
return NO;
}
The right approach seems to push a similar peoplePicker View on the NavigationController of the ModalView, but I don't know how.
If anyone had any idea it would be great!
If you want to see such a behavior in action you can have a look at the Amazon app: If you go through the first steps of an order you can select a shipping address exactly this way: From Contact List -> Select a Person -> Select an Address -> Select a Telephone number.
There, everything (seems to) take place in the modal view with just a navigation hierarchy with one more level than in the standard code shown above.
I guess this might be what you want:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier
{
ABPersonViewController *controller = [[ABPersonViewController alloc] init];
controller.displayedPerson = person;
controller.displayedProperties = [NSArray arrayWithObject:[NSNumber numberWithInt:kABPersonPhoneProperty]];
controller.personViewDelegate = self;
[peoplePicker pushViewController:controller animated:YES];
[controller release];
return NO;
}
- (BOOL)personViewController:(ABPersonViewController *)personViewController
shouldPerformDefaultActionForPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifierForValue
{
ABMutableMultiValueRef multi = ABRecordCopyValue(person, property);
CFStringRef phone = ABMultiValueCopyValueAtIndex(multi, identifierForValue);
NSLog(#"phone %#", (NSString *)phone);
CFRelease(phone);
ABPeoplePickerNavigationController *peoplePicker = (ABPeoplePickerNavigationController *)personViewController.navigationController;
[peoplePicker dismissModalViewControllerAnimated:YES];
return NO;
}
The idea is, to create another ABPersonViewController instance, and let your people picker to push it, since ABPeoplePickerNavigationController is a subclass of NSPeoplePickerNavigationController.
In the suggested answer there is a release missing
CFRelease(multi);
Without this release a leak will occur. Or at least according to the Build and Analyze in Xcode....
The following method should return NO:
- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController*)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
...
return NO;
}
This will allow your next method be called (peoplePickerNavigationController:shouldContinueAfterSelectingPerson:property:identifier:).
In my iPhone app Pastie, I took a different approach.
(source: manicwave.com)
I use the peoplePicker to select the person and then open a contact (person) editor.
This is just a simple view:
Contact Name
Phone Number > defaults to first phone number
email Address > defaults to first email address
Each of phone number and email address bring up another view showing the list of phones or email addresses, with a check mark next to the currently selected one.
I use this view for initial setup of a contact as well as subsequent editing.

ABPersonViewController Usage for displaying contact

Created a View based Project and added a contact to the AddressBook using ABAddressBookRef,ABRecordRef now i wanted to display the added contact ABPersonViewController is the method but how to use in a view based project
Write this piece of code in navigation controller.m:
ABAddressBookRef addressBook= ABAddressBookCreate(); // this will open the AddressBook of the iPhone
CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook); // this copies all the contacts from the Address Book into the array
NSString *contactName = [[NSString alloc] init];
// specify the contact name to be edited
contactName = #"ABCD";
for (int i =0 ;i<ABAddressBookGetPersonCount(addressBook);i++){
ABRecordRef ref = CFArrayGetValueAtIndex(people, i);
NSString *firstName = (NSString *)ABRecordCopyValue(ref,kABPersonFirstNameProperty); // this gets the First Name of the person
// check whether the editable contact exists in the AddressBook if exists then allows the user to edit the contact
if ([contactName compare: firstName] == NSOrderedSame) {
ABPersonViewController *personController = [[ABPersonViewController alloc] init];
personController.addressBook = addressBook; // this passes the reference of the Address Book
personController.displayedPerson = ref; // this sets the person reference
personController.allowsEditing = YES; // this allows the user to edit the details
personController.personViewDelegate = self;
personController.navigationItem.rightBarButtonItem = [self editButtonItem]; // this will add the inbuilt Edit button to the view
// this displays the contact with the details and presents with an Edit button
[[self navigationController] pushViewController:personController animated:YES];
[personController release];
}
}
// setEditing method needs to be overridden for edit functionality to work properly
------------------
- (void)setEditing:(BOOL)flag animated:(BOOL)animated {
[super setEditing:flag animated:animated];
if (flag == YES){
// change the view to an editable view
[ [self navigationController] setEditing:YES animated:NO];
}
else {
// save the changes and change the view to noneditable
[ [self navigationController] setEditing:NO animated:NO];
}
}
- (BOOL)personViewController:(ABPersonViewController *)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue {
return YES;
}