I have a Controller A and there is a UIButton, which on click I am presenting a new Controller B. But the problem is that the controller B is first embedded with a NAV. So ultimately I am presenting the UINavigationController.
Now there is a UIButton in Controller B on which the controller will dismiss and a delegate should be passed on controller A with some message
Controller A UIButtonCode
- (IBAction)summaryButtonClick:(id)sender {
UIStoryboard* storyBoard=[UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController* summaryVC=[storyBoard instantiateViewControllerWithIdentifier:#"SummaryNavVC"];
[self presentViewController:summaryVC animated:YES completion:nil];
summaryVC=nil;
}
Now Controller B
.h file
#import <UIKit/UIKit.h>
#protocol SummaryViewWhatsNewDelegate <NSObject>
#required
- (void) SummaryViewWhatsNew:(NSString*)title;
#end
#interface SummaryViewController :
UIViewController<UITableViewDataSource,UITableViewDelegate>
{
id <SummaryViewWhatsNewDelegate> _delegate;
}
#property (nonatomic,strong) id delegate;
#property (weak, nonatomic) IBOutlet UITableView *summaryTableView;
- (IBAction)closeSummaryView:(id)sender;
#end
.m
//Button Click
[self dismissViewControllerAnimated:YES completion:^{
[_delegate SummaryViewWhatsNew:#"Sales Triggers Filter"];
}];
I have already made the implementation of delegate in my Controller A
.h
#interface ControllerA : UIViewController<SummaryViewWhatsNewDelegate>
.m of Controller A
#pragma mark -ControllerB Delegate
-(void)SummaryViewWhatsNew:(NSString *)title{
NSLog(#"Delegate Called");
}
In this case I know I haven't provided the delegate.self part as I am presenting the NAV controller and not the Controller B
So I made a Object in viewDidLoad and Controller *B and set the delegate to self. But it doesn't work and delegate is never called
On the other hand if I only present the Cntroller B without Navigation and just before presenting I keep the b.delegate=self, it works.
Another alternate can be firing Notifications. But I want to work with delegates.
So is there any way to call the delegate of the presented view controller which is embedded by Nav. Any help will be highly appreciated.
Well I got the answer
We have to fetch the Controller object from NAV
Where I a presenting I just need to add these lines and it worked
UIStoryboard* storyBoard=[UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController* summaryVC=[storyBoard instantiateViewControllerWithIdentifier:#"SummaryNavVC"];
//Add These lines in order to get the object of Controller B.
// SummaryViewController is my Controller B
SummaryViewController* summary=[[summaryVC viewControllers] objectAtIndex:0];
summary.delegate=self;
[self presentViewController:summaryVC animated:YES completion:nil];
And it worked.
Related
I have an issue need to support:
Assume, I have the controller A and View Controller B. The view controller A present view controller B. After that view controller B load content completed. At View controller B I have a button.
How to dismiss both view controller when I touch event button touch up inside?
Here my code: At view controller A
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"mainstoryboard" bundle:nil];
ViewControllerB *viewcontrollerB = [storyBoard instantiateViewControllerWithIdentifier:#"viewcontrollerB"];
[self presentViewController:viewcontrollerB animated:YES completion:nil];
And code in view controller B
- (IBAction)buttonTouchUpInside:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
Thanks for helping me. You will save my time. :)
Use delegation. When your button pressed call delegate, and in delegate method implementation write following:
[self dismissViewControllerAnimated:NO completion:nil];
Use this delegation on your ViewControllerB
On ViewControllerB.h do this
#protocol ViewControllerDismissDelegate;
#interface ViewControllerB : UIViewController
#property(nonatomic) id<ViewControllerDismissDelegate> delegate;
#end
#protocol ViewControllerDismissDelegate <NSObject>
#optional
- (void)didViewControllerBDismiss;
#end
On ViewControllerB.m do this
// Button action
- (void)buttonDidClick {
if ([self.delegate respondsToSelector:#selector(didViewControllerBDismiss)]) {
[self dismissViewControllerAnimated:NO completion:nil];
[self.delegate didViewControllerBDismiss];
}
}
Learn more about delegates and data sources here
https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaEncyclopedia/DelegatesandDataSources/DelegatesandDataSources.html
My first view in the viewDidLoad has the following code
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Dialpad" bundle:nil];
self.vc = [sb instantiateViewControllerWithIdentifier:#"DialpadBoard"];
self.vc.delegate = self;
The header file contains the definition of the view controller
#property (nonatomic, retain) DialpadTableViewController *vc;
after catching an event the view loads a new modal view
- (void)handleEvent:(UIGestureRecognizer*)recognizer {
[self presentViewController:self.vc animated:YES completion:NULL];
}
The view also contains the method to dismiss the modal view:
- (void) dialpadControllerDidCancel:(SearchDialpadTableViewController *)controller {
[self dismissViewControllerAnimated:YES completion:nil];
}
The last method never gets called.
The problem is that the modal view when it is loaded has nil self.delegate. The new modal view is loaded from the storyboard as seen below. Why the delegate is nil? I cannot how a segue since the view is in another storyboard.
you can try this
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Dialpad" bundle:nil];
UINavigationController *nav= [sb instantiateViewControllerWithIdentifier:#"DialpadBoard"];
((SearchDialpadTableViewController *)[nav viewControllers][0]).delegate = self;
[self presentViewController:nav animated:YES completion:NULL];
Since we have the nav let's take the first controller and assign the delegate
the trick ;)
((SearchDialpadTableViewController *)[nav viewControllers][0]).delegate = self;
Does SearchDialpadTableViewController define a delegate protocol and does it have a property that is specific to that protocol?
The header for that file should look something like:
#protocol ViewControllerDelegateProtocol <NSObject>
- (void)dialpadControllerDidCancel:(SearchDialpadTableViewController *)controller;
#end
#interface ViewController : UIViewController
#property (weak, nonatomic) id<ViewControllerDelegateProtocol> searchPadDelegate;
#end
Then when the user taps Done which is I'm assuming what you're trying to do (send a delegate message when that happens). You would write something like
- (IBAction)donePressed:(id)sender
{
if ([self.searchPadDelegate respondsToSelector:#selector(dialpadControllerDidCancel)]) {
[self.searchPadDelegate dialpadControllerDidCancel:self];
}
}
you must be certain, that self.vc is a class, that you expected. It can be also NavigationController
What I did:
I am using scrollview to view some UIView(s), with paging enabled.
In last page in subview of scrollView I added a button.
I also wrote a function which is in subclass of UIView ,which is invoked when we press that button.
I want to view storyboard when I press that button.
You need to implement protocol method for custom UIView class.
For example;
#import <UIKit/UIKit.h>
#protocol YourCustomViewDelegate <NSObject>
- (void)buttonTapped;
#end
#interface YourCustomView : UIView
#property (nonatomic, strong) id< YourCustomViewDelegate > delegate;
#end
And the .m file you can call buttonTapped delegate method.
- (void)myCustomClassButtonTapped:(id)sender
{
[self.delegate buttonTapped];
}
For proper work;
set your custom view delegate to self in your custom view controller.
add buttonTapped method to that view controller
And do what you want in that method. Present/Push view controllers like the other answers explained.
Edit
I will try to illustrate very simple usage of protocols, hope it will help you.
#import "MyViewController.h"
#import "YourCustomView.h"
#interface MyViewController ()<YourCustomViewDelegate> // this part is important
#end
#implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
YourCustomView *customView = // initialize your custom view, I suppose that you already did it
customView.delegate = self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)buttonTapped
{
YOUR_VIEW_CONTROLLER_CLASS *viewCon =[storyboard instantiateViewControllerWithIdentifier:#"mainVC"]; //mainVC is just a example and u will have to replace it with your viewController storyboard id
//Pushing VC
[self.navigationController pushViewController:viewCon animated:YES];
}
Take a look at this
YourViewController *obj=[[YourViewController alloc]init];
UINavigationController *nav=[[UINavigationController alloc]initWithRootViewController:obj];
[[[UIApplication sharedApplication]keyWindow].rootViewController presentViewController:nav animated:YES completion:NULL];
try like this
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController* initialView = [storyboard instantiateInitialViewController];
Firstly you need to set a storyboard Id to your ViewController, namely "mainVC". Then you could pus/present it using below code :-
YOUR_VIEW_CONTROLLER_CLASS *viewCon =[storyboard instantiateViewControllerWithIdentifier:#"mainVC"]; //mainVC is just a example and u will have to replace it with your viewController storyboard id
//Pushing VC
[self.navigationController pushViewController:viewCon animated:YES];
//OR presenting VC
[self presentViewController:viewCon animated:YES completion:nil];
Also in case if you want your another storyboard to be initiated then below,
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil]; //Change MainStoryboard with your storyboard id
hope this will help
the way i perceive your question is
->Rightnow your inside you are in UIView class and inside it there is a button by clicking it you want to push or present a ViewController and offcourse from inside your UIView class you cant push or present your view Controller. So
you can do one simple thing first inside action method make a ref(forward declaration) or you can make a whole new object of your ViewController class in which your UIView is present right now , then call a function(which exist in your ViewController) like
//function inside your uiview calss
- (void)btnaction
{
[_objCSInformationViewController pushViewController];
}
// function inside your view controller
-(void)pushViewController
{
yourViewController *objViewController = [[yourViewController alloc]initWithNibName:#"yourViewController" bundle:nil];
[strong.navigationController pushViewController:objViewController animated:YES];
}
I have two view controllers. We'll call them listViewController and mapViewController. The listViewController shows first, a user taps a button that shows the mapViewController. The user taps a button on a annotation which is where my problems start.
When the user taps a button on mapViewController, I would like to call a method listViewController and dismiss mapViewController. To do this I am using this code:
mapViewController.m
listViewController* lvc = [[listViewController alloc] initWithNibName:nil bundle:nil];
[lvc getInformation:StringParameter];
[self dismissViewControllerAnimated:YES completion:nil];
However, when executing getInformation it seems that the listViewController class has been dealloc'd because all of the objects that I initialized in the viewDidLoad on listViewController are now nil including self, which just breaks everything.
I assume I'm creating the listViewController object incorrectly in mapViewController. I've tried it with a nil for nibName with the same result.
Ok, Let me clear one thing. On listViewController, you presentViewController a mapViewcontroller right? And you want invoke getInformation of the instance from mapViewController. In the code you're added, you instantiate listViewController again. You have 2 different instance of listViewController.
One option is to use a delegate pattern:
In your MapViewController.h file:
#protocol MapViewControllerDelegate <NSObject>
-(void)dismissMe;
-(void)getInformation:(NSString *)stringParameter;
#end
#interface MapViewController : UIViewController
#property (weak)id <MapViewControllerDelegate> delegate;
#end
In your MapViewController.m file:
-(void)annotationButtonTap:(id)button
{
[self.delegate getInformation:stringParameter];
[self.delegate dismissMe];
}
In your ListViewController.h
#import "MapViewController.h"
#interface ListViewController : UIViewController <MapViewControllerDelegate>
-(void)dismissMe
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)getInformation:(NSString *)stringParameter
{
//do whatever you plan with stringParameter
}
And somewhere in you ListViewController.m file where you create the MapViewController instance:
mapViewController = [[MapViewController alloc] initWithNibName:#"MapViewController" bundle:nil];
mapViewController.delegate = self; //make sure you do this
I have a view which opens a modal seque View.
I open this view with this code:
- (IBAction)openInfopage:(UIButton *)sender;
{
[self performSegueWithIdentifier:#"Infopage" sender:self.view];
}
I close this View with:
- (IBAction)closeView:(id)sender {
// old version:
//[self dismissViewControllerAnimated:YES completion:nil];
// my new version:
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
When the modal is closed, I want to update the view with the new datas the modal view generated.
I use [self.tableView reloadData]; to update, but where can I put this code, so it will start?
I try the viewWillAppear, but this isn't called when I close the modal view.
I always put these things in a delegate-protocol. So just insert this to your modal-viewcontroller.h:
#protocol MyDelegateProtocol <NSObject>
#optional
-(void)modalFinished;
#end
#interface ViewController : UIViewController
#property (nonatomic, weak) id <MyDelegateProtocol> delegate;
#end
And in the .m call this:
if(_delegate) [_delegate modalFinished];
When you are done. In the presenting ViewController you have to omplement this:
<MyDelegateProtocol>
after the #implementation line. And implement the delegate-method -(void)modalFinished. In this method you can do your refresh. And of course set the delegate property from the modal-viewcontroller to self in the presenting view controller.
EDIT:
MyViewController mvc = ...;
MyViewController.delegate = self;
[self presentViewController:...];
and if you present via segue:
in prepareForSegue:
MyViewController *mvc = segue.destinationViewController;
mvc.delegate = self;