1

I have a subclass of ABNewPersonViewController defined in storyboard, and embedded there in a navigation controller, as required by the docs. The navigation controller is itself controlled by a tab bar controller. In the identity inspector, the class has been set to the subclass.
enter image description here
In the subclassed ABNewPersonViewController I do the test initialization in viewDidLoad:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.newPersonViewDelegate = self;

    ABRecordRef newPerson= ABPersonCreate();
    CFErrorRef error = NULL;
    ABRecordSetValue(newPerson, kABPersonFirstNameProperty, CFSTR("First"), &error);
    ABRecordSetValue(newPerson, kABPersonLastNameProperty, CFSTR("Last"), &error);
    assert(!error);
    [self setDisplayedPerson:newPerson];
}  

In my subclass I have also implemented the delegate method newPersonViewController:didCompleteWithNewPerson:, but this does not matter.
When I select the tab in the tab bar controller, a black screen is displayed.
Any idea what I am doing wrong?
PS: I know how to set it up programmatically, but I would like to do it in storyboard.

EDIT

When I do it programmatically, the subclass is initialized by alloc & init. This works correctly. When the subclass is instantiated from storyboard, it receives initWithCoder:. To test it, I implemented initWithCoder: in the following way:

- (id)initWithCoder:(NSCoder*)coder{  
    self = [super init];  
    return self; 
}

In this case, the entry mask of ABNewPersonViewController is indeed displayed, but the navigation bar is not shown empty. I know this initialization hack is wrong, but does anybody know how to do it right?

EDIT

The navigation bar was not shown, because I set it to hidden. Normally, it is shown, but the buttons "done" and "cancel" are missing. This is of course no surprise, because the superclass is not initialized by initWithCoder: but by init.
Still the question is why the entry mask is not shown, but a black screen only.

Reinhard Männer
  • 14,022
  • 5
  • 54
  • 116

2 Answers2

2

Use following code to set up ABNewPersonViewController, its work for me fine :

  ABRecordRef newPerson= ABPersonCreate();
    CFErrorRef error = NULL;
    ABRecordSetValue(newPerson, kABPersonFirstNameProperty, CFSTR("Fname"), &error);
    ABRecordSetValue(newPerson, kABPersonLastNameProperty, CFSTR("Lanme"), &error);
    NSAssert(!error, @"something bad happend here.");


    ABNewPersonViewController* newPersonViewController = [[ABNewPersonViewController alloc] init];
    [newPersonViewController setDisplayedPerson:newPerson];
    [newPersonViewController setNewPersonViewDelegate:self];


    [self presentModalViewController:newPersonViewController animated:YES];

    CFRelease(newPerson);

------------- OR ---------

ABUnknownPersonViewController *picker = [[ABUnknownPersonViewController alloc] init];
            //  picker.unknownPersonViewDelegate = self;
            picker.displayedPerson = aContact;
            picker.allowsAddingToAddressBook = YES;
            picker.allowsActions = YES;
            picker.alternateName = @"";
            picker.title = @"Add to Contacts";
            picker.message = @"";
            [picker setHidesBottomBarWhenPushed:YES];
            [self.navigationController pushViewController:picker animated:YES];

Or for add new contact or add to existing contact you can use following one:

ABRecordRef aContact = ABPersonCreate();
    CFErrorRef anError = NULL;
    // store mobile number
    ABMultiValueRef mobilenumber = ABMultiValueCreateMutable(kABMultiStringPropertyType);
    bool didAdd = ABMultiValueAddValueAndLabel(mobilenumber, (__bridge CFTypeRef)(number), kABPersonPhoneMobileLabel, NULL);

    //store email address
    NSString *strEmail = [NSString stringWithFormat:@"%@",number];
    strEmail = [strEmail stringByReplacingOccurrencesOfString:@"mailto:" withString:@""];

    ABMutableMultiValueRef emailMultiValue = ABMultiValueCreateMutable(kABPersonEmailProperty);
    bool didAddEmail = ABMultiValueAddValueAndLabel(emailMultiValue, (__bridge CFTypeRef)(strEmail), kABOtherLabel, NULL);


    if (didAdd == YES || didAddEmail== YES) {
        ABRecordSetValue(aContact, kABPersonEmailProperty, mobilenumber, &anError);
        ABRecordSetValue(aContact, kABPersonEmailProperty, emailMultiValue, &anError);

        if (anError == NULL) {
            ABUnknownPersonViewController *picker = [[ABUnknownPersonViewController alloc] init];
            //  picker.unknownPersonViewDelegate = self;
            picker.displayedPerson = aContact;
            picker.allowsAddingToAddressBook = YES;
            picker.allowsActions = YES;
            picker.alternateName = @"";
            picker.title = @"Add to Contacts";
            picker.message = @"";
            [picker setHidesBottomBarWhenPushed:YES];
            [self.navigationController pushViewController:picker animated:YES];

//            UINavigationController *newNavigationController = [[UINavigationController alloc] initWithRootViewController:picker];
//            
//            [self presentViewController:newNavigationController animated:YES completion:nil];
//            
            picker = nil;
        } else {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                            message:@"Could not create unknown user"
                                                           delegate:nil
                                                  cancelButtonTitle:@"Cancel"
                                                  otherButtonTitles:nil];
            [alert show];
            alert = nil;
        }
    }
    CFRelease(mobilenumber);
    CFRelease(aContact);
Divya Bhaloidiya
  • 5,018
  • 2
  • 25
  • 45
  • Thanks for your answer! However my problem is NOT to create the ABNewPersonViewController by program, I have done this and it works. My problem is to set it up IN THE STORYBOARD. – Reinhard Männer Jul 05 '13 at 08:04
1

Try doing this, in the connection inspector of the TabBarController in the storyboard, there is a head 'Triggered Segues', make a connection from 'view controllers' to the 'ABNewPersonViewController'. Run your app, it will work.

If you need to further navigate, say from ABNewPersonViewController to ChildOfABNewPersonViewController, then you need to connect ABNewPersonViewController to the NavigationController and NavigationController's rootviewcontroller to ChildOfABNewPersonViewController.

Cheers !!

Say2Manuj
  • 709
  • 10
  • 20
  • Thanks for your answer! I looked it up: From the tab bar view controllers, I have triggered segues to the 3 navigation controllers that are triggered by selecting a tab. So the tab bar controller IS indeed linked with the nav controller that controls the ABNewPersonViewController. – Reinhard Männer Jul 04 '13 at 20:54
  • You present your tabs and then navigate to subsequent view controllers , so there is no need to connect TabBarController directly to a navigation controller, its after a view controller is presented via TabBarController, you navigate further. – Say2Manuj Jul 04 '13 at 21:03
  • I tried it: I removed the nav controller, and added the ABNewPersonViewController subclass directly to the tab bar controller, and it has a triggered segue to it. But the screen is still black... – Reinhard Männer Jul 04 '13 at 21:17