Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to present a view controller from another view controller

I am trying to open a ViewController from within another ViewController if certain conditions are met. The code seems to run without error but the view is never shown. I am new to xcode 4 /ios 5 so I must be missing something.

Here is the code responsible for opening the second viewcontroller:

CreateUserViewController *createUserController = [[CreateUserViewController alloc] initWithNibName:@"CreateUserView" bundle:[NSBundle mainBundle] keyWrapper:keyChainWrapper];

    [self presentViewController:createUserController animated:YES completion:nil];

In my project I have a xib called, "CreateUserView". I have added a view controller to this xib and assigned it to, "CreateUserViewController".

Also I noticed in the apple documentation that is shows setting the delegate of the viewcontroller to be presented. But it seems that no property called, "delegate" is on the viewcontroller object. Is this documentation old? This is the document I am trying to use (section 9-1):

View Controller Programming

Can someone give me a hint? Thanks..

edit Adding Custom Constructor

    -(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil keyWrapper:(KeychainItemWrapper *)keyWrapper
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if(self){
        [self setKeyChainWrapper:keyWrapper];
    } 
             return self;
}
like image 840
Nick Avatar asked Mar 23 '26 10:03

Nick


1 Answers

Regarding CreateUserView.xib: you don't want to put a CreateUserViewController object in the nib. You want to set the custom class of the File's Owner placeholder to CreateUserViewController. Then you need to connect the view outlet of File's Owner to the top-level view in the nib.

Regarding the delegate property: The UIViewController class doesn't have its own delegate property. The idea is that you add a delegate property to your subclass of UIViewController. The delegate provides a way for your presented view controller to pass custom information back to the presenting view controller.

Why would you want to do that? Let's consider the code you posted. I'll assume you have a UserListViewController that shows a list of User objects, and has a "Create new user" button. When the user touches the "Create new user" button, you create a CreateUserViewController and present it.

The user interacts with the CreateUserViewController to set the attributes of the new User object - name, rank, hairstyle, etc. Then he touches a "Done" button. Your CreateUserViewController creates the new User object and puts it in the database. Then it needs to dismiss itself, so the UserListViewController's list of User objects will appear again.

But you want the User list to include the newly created User object and you want to scroll the list so that the new User is on the screen. So you need a way to have your CreateUserViewController tell the UserListViewController about the newly created User object. This is where the delegate comes in.

You define a protocol like this:

@protocol CreateUserViewControllerDelegate

- (void)didCreateUser:(User *)user;

@end

and you give your CreateUserViewController a delegate property:

@interface CreateUserViewController

@property (weak, nonatomic) id<CreateUserViewControllerDelegate> delegate;

// ...

When your CreateUserViewController's "Done" button is touched, you notify your delegate of the new User:

- (IBAction)doneButtonWasTouched:(id)sender {
    User *user = [self createUser];
    [self.delegate didCreateUser:user];
    [self dismissViewControllerAnimated:YES completion:nil];
}

In your UserListViewController, you adopt and implement the protocol:

@interface UserListViewController <CreateUserViewControllerDelegate, UITableViewDelegate, UITableViewDataSource>

// ...

@end

@implementation UserListViewController

- (void)didCreateUser:(User *)user {
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.users count] inSection:0];
    [self.users addObject:user];
    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation: UITableViewRowAnimationAutomatic];
    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition: UITableViewScrollPositionNone animated:YES];
}

and when you need to present a CreateUserViewController, you set the new controller's delegate to the UserListViewController:

- (IBAction)createUserButtonWasTouched:(id)sender {
    CreateUserViewController *createUserController = [[CreateUserViewController alloc] initWithNibName:@"CreateUserView" bundle:[NSBundle mainBundle] keyWrapper:keyChainWrapper];
    createUserController.delegate = self;
    [self presentViewController:createUserController animated:YES completion:nil];
}
like image 189
rob mayoff Avatar answered Mar 24 '26 23:03

rob mayoff



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!