0
votes

I am presenting a modal view controller on the iPad which changes the presenting view controller while presented. For example:

  1. A view controller VC presents the modal view controller when the user selects a cell in a table view.
  2. The user selects an item on the modal view controller and another VC instance is opened in place of the first. Importantly, the view controller instance replacing the first is of the same type.
  3. The modal view controller cannot be dismissed or an EXC_BAD_ACCESS exception occurs.

The failing dismiss is understandable: the presenting view controller is no longer available. Basically, how would I dismiss this presented modal view controller from a different presenting view controller?

The code I already have is:

ViewController1.m

- (void)showModalViewController:(UIViewController *)viewController
{
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
    navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
    viewController.navigationItem.rightBarButton = [[UIBarButton alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissModalViewController)];
    [self presentViewController:navigationController animated:YES completion:nil];
}

- (void)dismissModalViewController
{
    [self dismissViewControllerAnimated:YES completion:nil];
    [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}
5
The 'navigationcontroller' or the 'viewcontroller' that you are presenting should have the responsibility to dismiss itself.Rom.
Why are you changing the presenting VC, particularly if the replacement is the same type?Wain
Which viewcontroller you are trying to dismiss? Is it self or the one which you are passing as an argument to showModalViewCntroller method??Augustine P A
i think if you present modelviewcontroller then dismissModelviewController instead of dismissViewConrollerjayraj m.g.

5 Answers

1
votes

Thanks for your suggestions but I solved the issue by using delegation. The presented view controller defined a delegate to notify the presenter when an action occurred.

ChildViewControler.h:

@protocol ChildViewControllerDelegate <NSObject>
- (void) childView:(ChildViewController *)childView didSelectItem:(Item *)item;
@end

ChildViewController.m:

// in interface
@property (nonatomic, weak) id <ChildViewControllerDelegate> delegate;

// in implementation
- (void)closeView:(Item *)anItem
{
    [self.delegate childView:self didSelectItem:anItem];
}

ViewController1.m:

- (void)showModalViewController:(UIViewController *)viewController
{
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
    navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
    viewController.navigationItem.rightBarButton = [[UIBarButton alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissModalViewController)];
    // Different view controller types may be passed here so check is required...
    if (viewController.class == [ChildViewController class]) {
        ((ChildViewController *)viewController).delegate = self;
    [self presentViewController:navigationController animated:YES completion:nil];
}

- (void)childView:(ChildViewController *)childView didSelectItem:(Item *)item
{
    [self dismissViewControllerAnimated:YES completion:nil];
    [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
    // Perform action required with 'item'
}
0
votes

You can try to change

self.presentingViewController 

(The view controller that presented this view controller or its farthest ancestor.) property in your modal View Controller before dismissing.

0
votes

Here is your problem:

 //...
        viewController.navigationItem.rightBarButton = [[UIBarButton alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissModalViewController)];
    //...
- (void)dismissModalViewController
{
    [self dismissViewControllerAnimated:YES completion:nil];
    [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}

You try to dismiss presenter view controller (that is currently seems to be swithced to another already) instead of presented modal view controller (in your case it UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];) so (if presenters view controllers not the tabs of tabViewController or not stored in navigationController's stack or somewhere else) you must to store reference to it somewhere else than in presenter view controller which will be switched and could be deallocated.

0
votes

As per document presentingViewController is a readonly property. You could not modify it.

@property(nonatomic,readonly) UIViewController *presentingViewController NS_AVAILABLE_IOS(5_0);
0
votes

I have not tested this code but there may be error in dismissModalViewController.
please put break point on this method the first line is perfect may your second line may cause error,may self.tableView is not accessible or self.tableView indexPathForSelectedRow may be nil.

    - (void)dismissModalViewController
{
    [self dismissViewControllerAnimated:YES completion:nil];    
    [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}

Thanks.