I have implemented protocol in my app,
I have declared protocol method in loginViewController and i am calling protocolMethod from confirmViewController
Here is my code snippet:
loginViewController.h
#protocol FirstControllerDelegate<NSObject>
#required
-(void)protocolMethod;
#end
#interface loginViewController : UIViewController<FirstControllerDelegate>
#end
loginViewController.m
- (IBAction)loginBtnClicked:(id)sender {
confirmViewController *obj = [confirmViewController new];
obj.delegate=self;
[self performSegueWithIdentifier:#"confirmloginsegue" sender:self];
}
-(void)protocolMethod{
NSLog(#"--- This is not callled ---");
[self dismissViewControllerAnimated:NO completion:nil];
}
Code for
confirmViewController.h
#interface confirmViewController : UIViewController
#property (nonatomic, assign) id <FirstControllerDelegate> delegate;
#end
confirmViewController.m
(IBAction)continueClicked:(id)sender {
[_delegate protocolMethod]; //Calling protocol method...
[self dismissViewControllerAnimated:YES completion:nil];
}
Where i am doing mistake?
Please help and thanks in advance!
Wrong Approach and delegate initialisation
In this lines:-
confirmViewController *obj = [confirmViewController new];
obj.delegate=self;
[self performSegueWithIdentifier:#"confirmloginsegue" sender:self];
--- You are loosing the object here
Solution
In your attribute inspector give the identifier for that confirmViewController, now push the vc and set the delegate for the object confirmViewController like this:-
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
ConfirmViewController *confirmViewController = [storyboard instantiateViewControllerWithIdentifier:#"ConfirmViewController"];
confirmViewController.delegate=self;
[self.navigationController pushViewController:confirmViewController animated:YES];
The delegating class does not exist for long enough to matter:
- (IBAction)loginBtnClicked:(id)sender {
confirmViewController *obj = [confirmViewController new];
obj.delegate=self;
[self performSegueWithIdentifier:#"confirmloginsegue" sender:self];
// obj is destroyed here
}
You need to implement prepareForSegue and set delegate there e.g.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
confirmViewController *destViewController = (confirmViewController *)segue.destinationViewController;
destViewController.delegate=self;
}
for further detail check this link:- http://www.appcoda.com/storyboards-ios-tutorial-pass-data-between-view-controller-with-segue/
You have to set delegate there. please,make some correction in your code like:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
confirmViewController *destViewController = (confirmViewController *)segue.destinationViewController;
destViewController.delegate=self;
}
You shoul use preparefrosegue to set your delegate object. so your code should be like this,
- (IBAction)loginBtnClicked:(id)sender {
[self performSegueWithIdentifier:#"confirmloginsegue" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
confirmViewController *obj = [confirmViewController new];
//or
confirmViewController *obj = [segue destinationViewController];
obj.delegate=self;
}
hope this will help ;)
If u are using View controller
SettingsHubViewController *settingVC = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"yourStoryBoardIdentifier"];
settingVC.delegate = self;
If u are using XIB load the NIB after that set the settingVC.delegate = self;
its working for me (I created OverLay view and loaded in main class)
Related
I have gone through most of the previous related posts, but although I have followed them correctly (as far as i understood), I simply am not able to trigger the delegate method for below code.
Objective: ModalView generates a string *SQL_String. Press DONE to dismiss the ModalView and trigger the delegate method in the parentview to get that *SQL_String.
SearchModalViewController.h
#protocol SearchControllerDelegate
- (void)didDismissModalView:(NSString *)SQL_String;
#end
#interface SearchModalViewController : UIViewController
#property (nonatomic, assign) id <SearchControllerDelegate> searchDelegate;
- (IBAction)handleDone:(id)sender;
SearchModalViewController.m
#interface SearchModalViewController ()
#end
#implementation SearchModalViewController
#synthesize searchDelegate;
- (IBAction)handleDone:(id)sender {
[self dismissView:sender];
}
- (void)dismissView:(id)sender {
[searchDelegate didDismissModalView:#"Test"];
[self dismissViewControllerAnimated:YES completion:nil];
}
DetailViewController.m (My parent View Controller)
#interface DetailViewController () <SearchControllerDelegate>
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
SearchModalViewController *searchModal = [[SearchModalViewController alloc] init];
searchModal.searchDelegate = self;
}
PROBLEM:
Below delegate method is not getting triggered.
- (void)didDismissModalView:(NSString *)SQL_String {
[self dismissViewControllerAnimated:YES completion:nil];
NSLog(#"The string = %#", SQL_String);
}
Any idea where I am doing wrong?
EDIT: Thank you guys. With your fast suggestions, I am able to close it down by adding below code instead of my previous IB connection.
- (IBAction)showSearchModal:(id)sender {
SearchModalViewController *searchModal = [self.storyboard instantiateViewControllerWithIdentifier:#"search"];
searchModal.searchDelegate = self;
searchModal.modalPresentationStyle = UIModalPresentationFormSheet;
searchModal.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:searchModal animated:YES completion:nil];
}
Here it goes
Change DetailViewController.m
- (IBAction)pushToSearch:(id)sender{
SearchModalViewController *searchModal = [self.storyboard instantiateViewControllerWithIdentifier:#"search"];
searchModal.searchDelegate = self;
[self presentViewController:searchModal animated:YES completion:nil];
}
And it will work.
Firstly, make sure your dismissView: of the SearchModalViewController is getting triggered.
Secondly, make sure your searchDelegate in the dismissView: method is not nil.
You need to set the delegate when you present the SearchModalViewController. The reason why your code doesn't currently work, is because the modal view controller's delegate is nil.
Update:
You set the delegate in prepareForSegue:sender:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)__unused sender
{
if ([[segue identifier] isEqualToString:#"modalSearch"])
{
SearchModalViewController *controller = (SearchModalViewController *)[segue destinationViewController];
controller.delegate = self;
}
}
I was test the delegate pass the value in objective-c.
I know there are other methods can pass string between UIViewControllers like NSNotifyCenter..etc.
Now I want to try to use the delegate pass value .
But I encounter some problems.
I use the navigation and there have two UIViewController(FirstUIViewcontroller and SecondUIViewController).
Now I want to use manual to change to SecondUIViewController,not use the button drag to the SecondUIViewController at FirstUIViewController.
So I add the code in the FirstUIViewController.m button action.
- (IBAction)pushBtnAction:(id)sender {
SecondViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
[self.navigationController pushViewController:controller animated:YES];
}
Then I want to pass the value from the SecondUIViewcontroller when I pop the view controller.
So I add the delegate implement and se the delegate in the FirstUIViewController.m.
- (void)viewDidLoad {
[super viewDidLoad];
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
secondVC = (SecondViewController*)[mainStoryboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
secondVC.delegate = self;
}
-(void) passSecondVC:(SecondViewController *)vc didAddValue:(NSString *)str
{
NSLog(#"second str:%#",str);
}
In the SecondUIViewController.h , I had declare delegate method.
#class SecondViewController;
#protocol SecondViewControllerDelegate <NSObject>
#optional
-(void)passSecondVC:(SecondViewController*)vc didAddValue:(NSString*) str;
#end
#interface SecondViewController : UIViewController
#property (nonatomic,assign) id<SecondViewControllerDelegate> delegate;
- (IBAction)passValueDelegatBtnAction:(id)sender;
In the SecondViewController.m ,
when I click the button will pop self uiviewcontroller and pass the value to FirstUIViewController.
- (IBAction)passValueDelegatBtnAction:(id)sender {
if( [self.delegate respondsToSelector:#selector(passSecondVC:didAddValue:)])
{
[self.delegate passSecondVC:self didAddValue:#"this is string from sencond vc"];
}
[self.navigationController popViewControllerAnimated:YES];
}
(My problems)
But in this status , I always can't get the value in the delegate method in the FirstUIViewController.
I had try to other method like below in the FirstViewController.m
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"segue");
id vc = segue.destinationViewController;
if( [vc isKindOfClass:[SecondViewController class]])
{
SecondViewController *secondVC = vc;
secondVC.delegate = self;
}
}
There are same problem.
I can't get the value from the delegate method.
Have anyone know where the problems?
I post my completely code in here.
Thank you very much.
Alright!
Remove your code from the viewDidLoad: method and set the delegate when you push the secondViewController.
- (IBAction)pushBtnAction:(id)sender {
SecondViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
[controller setDelegate:self];
[self.navigationController pushViewController:controller animated:YES];
}
So what was going wrong?
Ans: You create a new object in your viewDidLoad: method and set your firstViewController as delegate to it. Now while pushing you are creating another object of SecondViewController whose delegate is not set.
I downloaded your code & fixed it.
You don't want this line. so comment it,
// UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
// secondVC = (SecondViewController*)[mainStoryboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
// secondVC.delegate = self;
Edit this method as below,
- (IBAction)pushBtnAction:(id)sender {
SecondViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
controller.delegate = self;
[self.navigationController pushViewController:controller animated:YES];
}
Also edit this method as below,
- (IBAction)passValueDelegatBtnAction:(id)sender {
// if( [self.delegate respondsToSelector:#selector(passSecondVC:didAddValue:)])
// {
[self.delegate passSecondVC:self didAddValue:#"this is string from sencond vc"];
// }
[self.navigationController popViewControllerAnimated:YES];
}
you forgot some code in pushBtnAction..
- (IBAction)pushBtnAction:(id)sender {
SecondViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"]; // It's different to VC you init in viewDidLoad
controller.delegate = self; // you forgot....
[self.navigationController pushViewController:controller animated:YES];
}
prepareForSegue be call when you use segue to navigation.
I've got two view controllers, HomeViewController and AddViewController. HomeViewController is the delegate of AddViewController.
Problem is that when I hit the "Cancel" button in AddViewController, the call back to the delegate seems not to execute. Symptomatically, the Cancel button behaves as if it were not even wired up. Programmatically, breakpoints seem to indicate that control leaves the cancelButton method, yet never reaches addViewControllerDidCancel.
I believe everything is wired properly, and here's the relevant code:
From AddViewController.h:
#import <UIKit/UIKit.h>
#import "WMDGCategory.h"
#import "WMDGActivity.h"
#class HomeViewController;
#protocol AddViewControllerDelegate <NSObject>
-(void) addViewControllerDidSave;
-(void) addViewControllerDidCancel:(WMDGActivity *) activityToDelete;
#end
#interface AddViewController : UIViewController <UIPickerViewDataSource,UIPickerViewDelegate>
#property (nonatomic, weak) id <AddViewControllerDelegate> delegate;
From HomeViewController.h:
#interface HomeViewController : UITableViewController <UITableViewDataSource,UITableViewDelegate,AddViewControllerDelegate>
From HomeViewController.m:
-(void) addViewControllerDidSave
{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
[localContext MR_saveToPersistentStoreAndWait];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
[self refreshData];
}
-(void) addViewControllerDidCancel:(WMDGActivity *) activityToDelete
{
[activityToDelete MR_deleteEntity];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
[self refreshData];
}
And from AddViewController.m:
- (IBAction)cancelButton:(UIBarButtonItem *)sender
{
[self.delegate addViewControllerDidCancel:self.thisActivity];
}
Can someone spot my mistake?
Thanks!
Edit in response to answer 1 below:
Actually, I did this in my prepareFroSegue method in HomeViewController:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
if ([[segue identifier] isEqualToString:#"addModal"])
{
UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
AddViewController *avc = (AddViewController *)navController.topViewController;
avc.delegate = self;
WMDGActivity *addedActivity = (WMDGActivity *)[WMDGActivity MR_createInContext:localContext];
avc.thisActivity = addedActivity;
}
}
Your missing assigning the delegate object of your AddViewController instance, from what I can see it's still nil
myAddViewController.delegate = self; // 'self' is an example, should be myHomeViewController instance
EDIT:
You are calling this in your code:
[self.delegate addViewControllerDidCancel:self.thisActivity];
Ask yourself what is the value of delegate? You have declared it, yes, but you have not set its value, so it must be nil. So when you instantiate your AddViewController you must set the delegate using the line I wrote before.
I'm trying to learn more about Objective C blocks and how they work. I've set up a simple project with two UIViewControllers embedded in a UINavigationController in Storyboard. I'm attempting to change the background color of the first ViewController's view from the second view controller. Here's some code:
ViewController.m
#implementation ViewController{
ColorBlock _colorBlock;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"theSegue"]){
SecondViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
vc.colorBlock = _colorBlock;
}
}
- (IBAction)moveToSecondViewController:(id)sender {
__weak id weakSelf = self;
_colorBlock = ^{
[[weakSelf view] setBackgroundColor:[UIColor redColor]];
};
}
SecondViewController.h
typedef void (^ColorBlock)(void);
#interface SecondViewController : UIViewController
#property (readwrite, copy) ColorBlock colorBlock;
#end
SecondViewController.m
- (IBAction)buttonTapped:(id)sender {
if(self.colorBlock){
self.colorBlock();
}
}
The first ViewController's background color isn't being changed because in the buttonTapped: method of SecondViewController.m, self.colorBlock is nil, causing the block invocation not to be called. I thought I had successfully set the block in prepareForSegue:sender:. Why is my block property nil?
In your prepareForSegue, the destination has already been instantiated. So assuming that SecondViewController is the destination, you can do:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"theSegue"]){
SecondViewController *vc = segue.destinationViewController;
NSAssert([vc isKindOfClass:[SecondViewController class]], #"destination is not SecondViewController class");
vc.colorBlock = _colorBlock;
}
}
I'm working sample app by storyboard.
When made popoverview, I used the way - 'Embed in navigation controller'.
But I'm getting a big trouble of delegate usage.
It's that don't delegate to popover view's.
[ViweController.m]
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"PopRootViewController"]){
NSLog(#"[segue destinationViewController] :%#", [segue destinationViewController]);
rootViewController = [[RootViewController alloc] init];
rootViewController.delegate = (id)self;
NSLog(#"%#---%#---%#", rootViewController.delegate, self, rootViewController);
}
}
-(void)didTap22 {
NSLog(#"delegate step 1 success!! ");
}
The result of this source like this :
[segue destinationViewController] :<UINavigationController: 0x88660a0>
<ViewController: 0x6b795e0>---<ViewController: 0x6b795e0>---<RootViewController: 0x6b7da60>
but [RootViewController] don't receive the delegation.
[RootViewController.m]
#implementation RootViewController
#synthesize items, delegate;
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
....
self.items = mutableFetchResults;
NSLog(#"333333..... %#, ....... %#", self.delegate, self);
}
results :
333333..... (null), ....... <RootViewController: 0x8866520>
RootViewController's delegation is null.
I can't find solution about this.
Anybody help me, please!
I suspect you didn't declare your delegate UIPopoverControllerDelegate in the class declaration of your view controller.
This line is suspicious:
rootViewController.delegate = (id)self;
you don't need to cast self normally if you made the declaration I am mentioning.