Refreshing data in a UIViewController after dismissing its presented modal view controller via delegate

abc123 picture abc123 · Mar 18, 2013 · Viewed 17.5k times · Source

I have the delegate working as the data is being passed from the modal to the presenting view controller. But the presenting view controller isn't showing the data it receives from the modal. I looked at other posts and they say to use the delegate/protocol method, but don't explain how/why the presenting VC refreshes. I'm assuming my delegate is setup incorrectly. Otherwise, what is the method to refresh the data? I've checked and the viewWillAppear and viewDidAppear doesn't get called.

SCCustomerDetailVC.h (Presenting VC)

#import "SCCustomersVC.h"

@interface SCCustomerDetailVC : UIViewController <SCCustomersVCDelegate>

@property (atomic, strong) SCCustomer *customer;
@property (strong, nonatomic) IBOutlet UIButton *changeCustomerButton;

- (IBAction)changeCustomerButtonPress:(UIButton *)sender;

@end

SCCustomerDetailVC.m (Presenting VC)

- (IBAction)changeCustomerButtonPress:(UIButton *)sender 
{    
    UINavigationController *customersNC = [self.storyboard instantiateViewControllerWithIdentifier:@"customersNC"];
    SCCustomersVC *customersVC = (SCCustomersVC *)customersNC.topViewController;
    customersVC.delegate = self;
    [self presentViewController:customersNC animated:YES completion:nil];
}

//Protocol methods
- (void)passCustomer:(SCCustomer *)customer
{
    self.customer = customer;

    //At this point, self.customer has the correct reference

    [self dismissViewControllerAnimated:YES completion:nil];
}

SCCustomersVC.h (Modal VC)

#import "SCCustomersVCDelegate.h"

@class SCCustomerDetailVC;

@interface SCCustomersVC : UIViewController <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate>

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

@end

SCCustomersVC.m (Modal VC)

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    SCCustomer *customer = [self customerAtIndexPath:indexPath];
    [self.delegate passCustomer:customer];
}

SCCustomersVCDelegate.h

@class SCCustomer;

@protocol SCCustomersVCDelegate <NSObject>
@optional

- (void)passCustomer:(SCCustomer *)customer;

@end

Answer

danh picture danh · Mar 18, 2013

I think you're nearly there. EDIT - just learned here that viewWillAppear behavior is different in iOS>5. You still want view will appear to update your view with your model state, since it needs to do that on initial presentation.

And it's fine to call it from either your modal vc or from within the delegate method. So add code to viewWillAppear that updates the view with the view controller's model state...

// SCCustomerDetailVC.m
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    // making up an IBOutlet called someLabel
    // making up a model method (description) that returns a string representing your model
    self.someLabel.text = [self.customer description];
}

Then either from the presented vc or the delegate, call viewViewWillAppear:

- (void)passCustomer:(SCCustomer *)customer
{
    self.customer = customer;
    [self viewWillAppear:YES];
    [self dismissViewControllerAnimated:YES completion:^{}];
}