lavitanien lavitanien - 3 months ago 8
Objective-C Question

Can't dismiss modal view when tap a button

In "FirstViewController" I declare a button which present the modal view "InfoViewController".

In "InfoViewController", I declare a toolbar with a "modalViewButton" UIButton which dismiss the modal view. But the "OK" UIButton doesn't work. I don't know why.

Here's FirstViewController.h

#import <UIKit/UIKit.h>
#import "InfoViewController.h"

@interface FirstViewController : UIViewController
{
InfoViewController *infoViewController;
}

@property (nonatomic, retain) InfoViewController *infoViewController;
@end


Here's FirstViewController.m

#import "FirstViewController.h"
@implementation FirstViewController
@synthesize infoViewController;

- (IBAction)modalViewAction:(id)sender
{
if (self.infoViewController == nil)
self.infoViewController = [[[InfoViewController alloc] initWithNibName:
NSStringFromClass([InfoViewController class]) bundle:nil] autorelease];
[self presentModalViewController:self.infoViewController animated:YES];
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}

- (void)dealloc
{
[infoViewController release];
[super dealloc];
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
[super viewDidLoad];

UIButton* modalViewButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[modalViewButton addTarget:self
action:@selector(modalViewAction:)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *modalBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:modalViewButton];
self.navigationItem.leftBarButtonItem = modalBarButtonItem;
[modalBarButtonItem release];
}

- (void)viewDidUnload
{
[super viewDidUnload];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end


Here's InfoViewController.h

#import <UIKit/UIKit.h>
@interface InfoViewController : UIViewController
{

}
-(IBAction)infoDismissAction:(id)sender;
@end


Here's the InfoViewController.m

#import "InfoViewController.h"

@implementation InfoViewController

- (IBAction)infoDismissAction:(id)sender
{
[self.parentViewController dismissModalViewControllerAnimated:YES];
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{

}
return self;
}

- (void)dealloc
{
[super dealloc];
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
[super viewDidLoad];

UILabel *infoLabel = [[UILabel alloc] init];
infoLabel.frame = CGRectMake(50, 100, 100, 40);
infoLabel.textAlignment = UITextAlignmentCenter;
infoLabel.text = @"About";
[self.view addSubview:infoLabel];

UIToolbar *toolBar;
toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
toolBar.frame = CGRectMake(0, 0, 320, 50);
toolBar.barStyle = UIBarStyleDefault;
[toolBar sizeToFit];

UIBarButtonItem *flexibleSpace = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil] autorelease];

UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:@"OK"
style:UIBarButtonItemStyleBordered
target:self
action:@selector(infoDismissAction:)];

UIBarButtonItem* infoTitle = [[UIBarButtonItem alloc] initWithTitle:@"About"
style:UIBarButtonItemStylePlain
target:self action:nil];

NSArray *barButtons = [[NSArray alloc] initWithObjects:flexibleSpace,flexibleSpace,infoTitle,flexibleSpace,doneButton,nil];

[toolBar setItems:barButtons];

[self.view addSubview:toolBar];

[toolBar release];
[infoTitle release];
[doneButton release];
[barButtons release];
[infoLabel release];
}

- (void)viewDidUnload
{
[super viewDidUnload];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end

Answer

I would solve this issue with a delegate method.

First make a protocol in your modalViewController

@protocol ModalViewDelegate <NSObject>

 - (void)didDismissModalView;

@end

And set a delegate property in the same modalVC:

id<ModalViewDelegate> dismissDelegate;

Then make a buttonActionMethod that calls the delegate in the modalVC:

- (void)methodCalledByButton:(id)sender 
{
    // Call the delegate to dismiss the modal view
    [self.dismissDelegate didDismissModalView];
}

Now your modalVC is done you have to prepare the mainVC calling the modalVC: You have to make your MainViewController comform to the delegate:

@interface MainViewController : UIViewController <ModalViewDelegate>

At the place you alloc your ModalViewController you have to set the delegate property you made in your modalViewController:

self.myModalViewController.dismissDelegate = self;

Now the MainViewController listens to the delegate and the only thing you need to do is implement the delegateMethod.

-(void)didDismissModalView
{
    [self dismissModalViewControllerAnimated:YES];
}

Now your ModalVC will dismiss on a buttonpress (at least when you call the method properly)

Hope this all makes sense. Good luck.