Cannot dismiss ABPersonViewController in iPhone - 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>

Related

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 ;)

MFMailComposeViewController in a separate class

I seek to create a "Utility Email sender class" that I can use in several iPhone projects.
I created MailSender header and implementation for that purpose.
MailSender.h:
#interface MailSender : NSObject<MFMailComposeViewControllerDelegate>
- (id) initWithParent:(UIViewController*) mainController;
- (void) invokeMailSender:(NSString*) to:(NSString*) subject:(NSString*) failureTitle:(NSString*) failureMessage:(NSString*) failureCancel;
#end
MailSender.m:
#import "MailSender.h"
#implementation MailSender
MFMailComposeViewController* mailer;
UIViewController* mailParentController;
- (id) initWithParent:(UIViewController*) mainController
{
if( self = [super init])
{
mailParentController = mainController;
}
return self;
}
- (void) invokeMailSender:(NSString*) to:(NSString*) subject:(NSString*) failureTitle:(NSString*) failureMessage:(NSString*) failureCancel;
{
if([MFMailComposeViewController canSendMail])
{
mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:subject];
NSArray *toRecipients = [NSArray arrayWithObjects:to, nil];
[mailer setToRecipients:toRecipients];
[mailParentController presentModalViewController:mailer animated:YES];
}
else
{
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:failureTitle message:failureMessage
delegate:nil cancelButtonTitle:failureCancel otherButtonTitles: nil];
[alert show];
}
}
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
// Do nothing
[mailParentController dismissModalViewControllerAnimated:YES];
mailer = nil;
}
#end
I called the class from a View Controller (in a button touch down action) using the following instructions:
#implementation InfoViewController
MailSender *sender;
- (IBAction)openMail:(id)sender
{
sender = [[MailSender alloc] initWithParent:self];
[sender invokeMailSender:#"test#test.com" :#"123" :#"123" :#"123" :#"123"];
}
....
#end
When I run the code, I am able to show the email views correctly. However, this is then followed by a crash.
Note that I do not have a crash when using MFMailComposeViewController directly from my UIViewController (And assigning the View Controller as the delegate),
Any ideas?
Sorry I am still a new to Objective C :)
You need to retain your sender MailSender instance. It is being released after you call the invoke message.
You could do this by declaring a property named sender. E.g.
#property (strong, nonatomic) MailSender *sender;
...
#synthesize sender = _sender;
...
self.sender = [[MailSender alloc] initWithParent:self];
[self.sender invokeMailSender:#"noor#dimachk.com" :#"123" :#"123" :#"123" :#"123"];
By the way, your method declaration is a bit funny. You should name the arguments. E.g.
- (void)invokeMailSender:(NSString *)sender
to:(NSString *)to
subject:(NSString *)subject
failureTitle:(NSString *)failureTitle
failureMessage:(NSString *)failureMessage
failureCancelButtonTitle:(NSString *)failureCancelButtonTitle

How to open the Edit contact window in iphone app?

I am adding contact info from my iPhone application on Addcontact click. I just want to open edit contact window on same Addcontact click so user can edit or delete the contact which just now have added. I have done smthing like below..
- (IBAction)AddContact
{
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef Showroom = ABPersonCreate();
//adding contact name as showroom name
ABRecordSetValue(Showroom, kABPersonFirstNameProperty, ShowroomName.text , nil);
ABAddressBookAddRecord(addressBook, Showroom, nil);
ABAddressBookSave(addressBook, nil);
// Fetch the address book
//ABAddressBookRef addressBook = ABAddressBookCreate();
// Search for the person named "Appleseed" in the address book
//ABRecordRef Showroom = (ABRecordRef)[Showroom objectAtIndex:0];
ABPersonViewController *picker = [[[ABPersonViewController alloc] init] autorelease];
picker.personViewDelegate = self;
picker.displayedPerson = Showroom;
// Allow users to edit the person’s information
picker.allowsEditing = YES;
[self.navigationController pushViewController:picker animated:YES];
}
this is my Map application. On launching I get showroom results with there contacts. This I can add in to the iPHone contact with edit contact window opening. But when I open other controller to pass user selected string address in to Map controller to search showroom location. The same above code is not working. I mean it only add the contacts but I didnt get the edit contact window.
Edit:
May be this problem is regarding navigation controller bar so check the below code also
- (void)viewWillAppear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:YES animated:animated];
}
- (void)viewDidLoad {
[self.navigationController setNavigationBarHidden:NO ];
self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:25.0/255.0f green:25.0/255.0f blue:25.0/255.0f alpha:1.0f];
}
- (void)viewWillDisappear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
I hope this code is works for you i implements that code and in my application works fine thank you
contecviewcontroller.h
#interface DetailsViewController : UIViewController
DocumentNavController *coffeeObj;
editViewController *evController;
int currentindex;
}
#property (nonatomic, retain) DocumentNavController *coffeeObj;
#property (readwrite, assign) int currentindex;
#end
contecviewcontroller.m
- (void)viewDidLoad {
[super viewDidLoad];
//self.navigationController.toolbar.tintColor = [UIColor darkGrayColor];
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemEdit
target:self action:#selector(goToEdit)]autorelease];
}
-(void)goToEdit{
if(evController == nil)
evController = [[editViewController alloc]initWithNibName:#"editViewController" bundle:nil];
evernoteAppDelegate *appdelegete = (evernoteAppDelegate *)[[UIApplication sharedApplication]delegate];
coffeeObj = [appdelegete.noteArray objectAtIndex:currentindex];
evController.Editcurrentindex = currentindex;
evController.docedObj = coffeeObj;
[self.navigationController pushViewController:evController animated:YES];
}

How to correctly use ABPersonViewController with ABPeoplePickerNavigationController to view Contact information?

Update 9/2/10: This code no longer works as of the iOS 4 update--it fails with an internal assertion. There is now a great Address Book API example available in the iPhone SDK Reference Library called "QuickContacts."
The example code is available here; it will help you solve this problem:
http://developer.apple.com/iphone/library/samplecode/QuickContacts/Introduction/Intro.html
I'm attempting to add a feature to my app that allows the user to select a contact from an ABPeoplePickerNavigationController, which then displays an ABPersonViewController corresponding to the contact they picked. At that point, I want the user to be able to click on a contact's phone number and have my app respond with custom behavior.
I've got the ABPeoplePickerNavigationController working fine, but I'm running into a problem displaying the ABPersonViewController. I can get the ABPersonViewController to animate onto the screen just fine, but it only displays the contact's photo, name, and company name. None of the contact's other fields are displayed.
I'm using the 'displayedProperties' element in the ABPersonViewController to tell the program to display phone numbers. This creates some strange behavior; when I select a contact that has no phone numbers assigned, the contact shows up with "No Phone Numbers" written in the background (as you'd expect), but when selecting a contact that does have a phone number, all I get is a blank contact page (without the "No Phone Numbers" text).
Here's the method in my ABPeoplePickerNavigationController delegate class that I'm using to create my PersonViewController class, which implements the ABPersonViewController interface:
- (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
BOOL returnState = NO;
PersonViewController *personView = [[PersonViewController alloc] init];
[personView displayContactInfo:person];
[peoplePicker pushViewController:personView animated:YES];
[personView release];
return returnState;
}
Here's my PersonViewController.h header file:
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <AddressBookUI/AddressBookUI.h>
#interface PersonViewController : UIViewController <ABPersonViewControllerDelegate>
{
}
- (void) displayContactInfo: (ABRecordRef)person;
#end
Finally, here's my PersonViewController.m that's creating the ABPersonViewController to view the selected contact:
#import "PersonViewController.h"
#implementation PersonViewController
- (void) displayContactInfo: (ABRecordRef)person
{
ABPersonViewController *personController = [[ABPersonViewController alloc] init];
personController.personViewDelegate = self;
personController.allowsEditing = NO;
personController.displayedPerson = person;
personController.addressBook = ABAddressBookCreate();
personController.displayedProperties = [NSArray arrayWithObjects:
[NSNumber numberWithInt:kABPersonPhoneProperty],
nil];
[self setView:personController.view];
[[self navigationController] pushViewController:personController animated:YES];
[personController release];
}
- (BOOL) personViewController:(ABPersonViewController*)personView shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue
{
return YES;
}
#end
Does anyone have any idea as to why I'm seeing this blank Contact screen instead of one with clickable phone number fields?
Alright, I think I'm getting closer to finding the problem. I'm fairly sure it's with this part of the displayContactInfo call above:
[self setView:personController.view];
When I omit this line, all I see is a blank screen when I click a contact. The ABPeoplePickerNavigationController is pushing the PersonViewController onto the NavigationController stack. The PersonViewController then instantiates an ABPersonViewController object, but for whatever reason the ABPersonViewController never gets properly added to the NavigationController stack.
Does anyone know how to add the ABPersonViewController to the stack, rather than just the PersonViewController?
Just a heads-up to anyone who runs into this problem themselves: I was able to product the correct behavior by instantiating the ABPersonViewController in its delegate's viewDidLoad() method as below:
As before, here's my ABPeoplePickerNavigationController delegate's method:
- (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
BOOL returnState = NO;
PersonViewController *personView = [[PersonViewController alloc] init];
[peoplePicker pushViewController:personView animated:YES];
[personView displayContactInfo:person];
[personView release];
return returnState;
}
Here's my PersonViewController.h (ABPersonViewController delegate) header file:
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <AddressBookUI/AddressBookUI.h>
#interface PersonViewController : UIViewController <ABPersonViewControllerDelegate>
{
ABPersonViewController *personController;
}
- (void) displayContactInfo: (ABRecordRef)person;
#end
Finally, here's the delegate's implementation (PersonViewController.m):
#import "PersonViewController.h"
#implementation PersonViewController
- (void) viewDidLoad
{
}
- (void) viewDidUnload
{
[personController release];
}
- (void) displayContactInfo: (ABRecordRef)person
{
personController = [[ABPersonViewController alloc] init];
[personController setDisplayedPerson:person];
[personController setPersonViewDelegate:self];
[personController setAllowsEditing:NO];
personController.addressBook = ABAddressBookCreate();
personController.displayedProperties = [NSArray arrayWithObjects:
[NSNumber numberWithInt:kABPersonPhoneProperty],
nil];
[self setView:personController.view];
}
- (BOOL) personViewController:(ABPersonViewController*)personView shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue
{
// This is where you pass the selected contact property elsewhere in your program
[[self navigationController] dismissModalViewControllerAnimated:YES];
return NO;
}
#end
Hopefully this ends up being helpful for someone. The AddressBook UI framework was a bit tricky for me to wrap my head around (although I'm new to iPhone development so I'm still learning a lot of the nuances of iPhone program organization).

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;
}