how does this set delegate method work? - ios

These are my delegate methods in Child view controller.
#protocol assignNames<NSObject>
-(void)setFirstName:(NSString*)firstName;
-(void)setLastName:(NSString*)lastName;
#end`
In my parent view controller, I receive the first name in a text field.
Here is a part of my code .
VIEWCONTROLLER.M
\\ FirstName is the name of my textField string
viewcontroller2 *viewc = [[viewcontroller2 alloc]init];
viewc2 = [segue destinationViewController];
viewc2.FNT = FirstName.text;
[viewc2 setDelegate:self ]; \\ Here is my question
So, when I give this method, what it actually means?? as nothing seems to happen if i include it in my code .

The #protocol block in your childviewController is a list of methods that a delegate of the childviewController should implement. When you call [viewc2 setDelegate:self ] from viewController.m, your viewController becomes a delegate of your childViewController.
So what does all these steps do? Well, firstly, because the parent VC subscribes to the assignNames delegate, it will have those two methods implemented. Secondly, the Child VC can call the protocol's methods in the parent VC like so:
[self.delegate setFirstName:#"Derp"];
// we are in the child VC and the delegate would be parent VC
Anyways, there was a time when all this baffled me, so I know how it is. I suggest you go through some tutorials to get a hang of the stuff, like this one here.

Related

ios Delegate Objective-c data sending from 2nd view controller to 1st view controller

I have 2 view controllers . First one is UIview controller and second one is table view controller.
I want to send data 2nd (table view controller) to first(uiview Controller) after the selection of rows of 2nd view controller.
For this i have written a delegate protocol.
But my delegate protocol is not working...
I figured out the problem.The object of second view controller that i am creating.
address = [[second_viewcontroller alloc] init];
address.delegate = self;
is different from self of second_viewcontroller view controller page.
How to make this two same.
self = [[second_viewcontroller alloc] init];
your problem my delegate protocol is not working... I figured out the problem.The object of second view controller that I am creating. address=[[second_viewcontroller alloc]init]; address.delegate=self; is different from self of second_viewcontroller view controller page.
It's clear say that way you create the second_viewcontroller object is not right.
You have to create the object from ViewController storyboard identifier.
First give the Storyboard ID to ViewController from Storyboard.Follow this step to Giving the Storyboard ID.
Select the particular ViewController in Storyboard.
Go to IdentityInspector.
Under IdentityInspector, There is identity section and add the Storyboard ID In "Storyboard ID" Field.
Syntax For Creating a ViewController Object.
Second_viewController *aVC = [self.storyboard instantiateViewControllerWithIdentifier:#"Second_viewController"];
aVC.delegate = self;
I assume that you are calling the Second_ViewController from storyboard instead of doing programmatically.
In that case, the correct instance of Second_ViewController can be accessed in prepareForSegue. For that, you need to set a Storyboard segue identifier, eg "Second_ViewController"
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"Second_ViewController"]) {
SecondViewController *aSecVC = segue.destinationViewController;
// Register the Delegate to self.So when we call the delegate method from secondVC, SendMessage will be call of ViewController
aSecVC.delegate = self;
}
}
If you use alloc-init or instantiateViewControllerWithIdentifier, when you are using a storyboard push segue, it will create another instance.
Yes as your instantiating a new instance of the second view controller. From what I could make out from your question, I guess if you obtain the instance of your secondViewController from the Navigation Stack it should work
I created a sample project for you to get the basic knowledge of how to pass data backward using NSUserDefaults. try this in GitHub. hope this will help to you. project url Pass data backward using NSUserDefaults in Objective-C

How To Call Parent Viewcontroller To Child Viewcontroller Method Using Objective C?

I have a button in mainviewcontroller, when that button is tapped I want to call a method on another view controller. Here below is an image showing my scenario, Green button click to call preview controller VC1 received method without navigation anything. I just need to call that method only!
Declare a method in .h file of VC1 and implement in .m file of VC1
Call that method from MainView Controller ,
Create a NSNotificationObserver in MainView Controller and implement it in .m file of MainView Controller ,
Now when method of VC1 is called and before it returns, fire a PostNotification from VC1 and pass the parameter which you want in MainView Controller.
#RobAu has given correct answer as you can use NSNotificationObserver and call from anywhere.
Other alternate which i have used is using protocol and is very simple.
Just declare a protocol in the child controller. while launching the view put the parent controller as delegate. now call the delegate method from where ever you want from child controller
Here is example which i used (In my case all the child controller was of same kind)
//ChildClass.h file of child class
#protocol updateIndex <NSObject>
-(void)updateMediaId:(NSString*)currentMediaId;
#end
#interface ChildClass : UIViewController
#property NSString *imageID;
#property id updateIndexDelegate;
#end
//ChildClass.m file for child class where you want to call the delegate method
(I called in viewDidAppear method)
-(void)viewDidAppear:(BOOL)animated{
[self.updateIndexDelegate updateMediaId:_imageID];
}
And in ParentClass.m file of parent class use the delegate to self like this
ChildClass *childObject = [[ChildClass alloc] init];
childObject.delegate = self;
and define the delegate method like this
-(void)updateMediaId:(NSString*)currentMediaId {
NSLog(#"%#",currentMediaId);
}
Enjoy coding

How to call a method inside a viewController from didSelectRowAtIndexPath

I have a method inside my viewController (MainViewController.m) that accepts a parameter (Let's say it changes the background color of the viewController based on the number):
-(void) methodThatDoesSomething:(int)indexNumber {}
Inside this viewController I have a UITableView, but the delegate of this table is another class (TableDelegateClass.m). So inside this class I have didSelectRowAtIndexPath.
How do I call the "methodThatDoesSomething" from didSelectRowAtIndexPath? If I do it like this:
MainViewController* mainView = [[MainViewController alloc] init];
[mainView methodThatDoesSomething:indexPath.row];
It doesn't work. As another instance of the class is created and it doesn't after the viewController that I'm currently using.
I can easily do it if the delegate of the table is the MainViewController (just with this code inside didSelectRowAtIndexPath) :
[self methodThatDoesSomething:indexPath.row]
but I want to organize better the code and have different classes, one for the table and another for the viewController containing the table.
One simple solution could be to define your own delegate protocol for -(void) methodThatDoesSomething:(int)indexNumber {} so you can set TableDelegateClass delegate to your viewController and then call [delegate methodThatDoesSomething:indexPath.row]; (after checking respondsToSelector).
You can also pass the viewController instance when you create TableDelegateClass but this is a higher coupling level than delegate.
One way to solve your problem is to create a property of type MainViewController in the delegate class and assign the controller instance to it.
But maybe this problem that you are having is an indicator that the tableView delegate should indeed be the MainViewController and not another class?

didSelectViewController does not get called on certain occasions

I have the problem that many already have reported, didSelectViewController doesn't get called, but in my case it sometimes gets called. I have three tabs and three view controllers. Every time user presses second or third tab I need to execute some code. In my SecondViewController and ThirdViewController I have:
UITabBarController *tabBarController = (UITabBarController *)[UIApplication sharedApplication].keyWindow.rootViewController;
[tabBarController setDelegate:self];
Now everything works fine with the SecondViewController, the didSelectViewController gets called every time the second tab is pressed. Also in ThirdViewController didSelectViewControllergets called every time the third tab is pressed but only when second bar is meanwhile not pressed. So when I switch back and forth between FirstViewController and ThirdViewController everything is OK. But when I go in a pattern like first->second->third, then didSelectViewController doesn't get called in ThirdViewController. Also when I go like first->third->second->third didSelectViewController gets called in ThirdViewController the first time but not the second time. Any ideas?
It's hard to follow what exactly you are doing, but from what I understand you are responding to tab switches by changing the UITabBarController's delegate back and forth between SecondViewController and ThirdViewController.
If that is true, I would advise against doing this. Instead I would suggest you try the following:
Assign a delegate that never changes. For a start you could use your app delegate, but it would probably be better if you had a dedicated small class for this. I am sure that now you have a non-changing delegate, it will get 100% of all the calls to tabBarController: didSelectViewController:.
The object that is the delegate must have a reference to both the SecondViewController and ThirdViewController instances. If you are designing your UI with Interface Builder, you might do this by adding two IBOutlets to the delegate class and connecting the appropriate instances to the outlets.
Now when the delegate receives tabBarController: didSelectViewController: it can simply forward the notification to either SecondViewController or ThirdViewController, depending on which of the tabs was selected.
A basic code example:
// TabBarControllerDelegate.h file
#interface TabBarControllerDelegate : NSObject <UITabBarControllerDelegate>
{
}
#property(nonatomic, retain) IBOutlet SecondViewController* secondViewController;
#property(nonatomic, retain) IBOutlet ThirdViewController* thirdViewController;
// TabBarControllerDelegate.m file
- (void) tabBarController:(UITabBarController*)tabBarController didSelectViewController:(UIViewController*)viewController
{
if (viewController == self.secondViewController)
[self.secondViewController doSomething];
else if (viewController == self.thirdViewController)
[self.thirdViewController doSomethingElse];
}
EDIT
Some hints on how to integrate the example code from above into your project:
Add an instance of TabBarControllerDelegate to the .xib file that also contains the TabBarController
Connect the delegate outlet of TabBarController' to the TabBarControllerDelegate instance
Connect the secondViewController outlet of TabBarControllerDelegate to the SecondViewController instance
Connect the thirdViewController outlet of TabBarControllerDelegate to the ThirdViewController instance
Add a method - (void) doSomething to SecondViewController
Add a method - (void) doSomethingElse to ThirdViewController
Make sure that you don't have any code left in SecondViewController and ThirdViewController changes the TabBarController delegate!
Once you are all set and everything is working fine, you will probably want to cleanup a bit:
Change the names of the notification methods doSomething and doSomethingElse to something more sensible
If you followed the discussion in the comments, maybe you also want to get rid of the secondViewController and thirdViewController outlets
I too had this problem and got fed up with it. I decided to subclass UITabBarController and override the following methods. The reason I did both was for some reason on application launch setSelectedViewController: wasn't being called.
- (void)setSelectedIndex:(NSUInteger)selectedIndex
{
[super setSelectedIndex:selectedIndex];
// my code
}
- (void)setSelectedViewController:(UIViewController *)selectedViewController
{
[super setSelectedViewController:selectedViewController];
// my code
}
I just dug through this tutorial on storyboards, and I thought of an alternative to using UITabBarControllerDelegate. If you want to stick to UITabBarControllerDelegate then feel free to ignore this answer.
First, create a subclass of UITabBarController, let's call it MyTabBarController. In the storyboard editor you need to change the "Class" property of the tab bar controller so that the storyboard picks up your new class.
Add this code to MyTabBarController.m
- (void) prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"SecondVC"])
{
SecondViewController* secondViewController = (SecondViewController*)segue.destinationViewController;
[secondViewController doSomething];
}
else if ([segue.identifier isEqualToString:#"ThirdVC"])
{
ThirdViewController* thirdViewController = (ThirdViewController*)segue.destinationViewController;
[thirdViewController doSomethingElse];
}
}
In the storyboard editor, you can now select the two segues that connect to SecondViewController and ThirdViewController and change the segue identifier to "SecondVC" and "ThirdVC", respectively.
If I am not mistaken, that's all you need to do.

Sharing data between ViewControllers

I have a simple Single View iOS 5 application that I added a second view controller to. I embedded these inside a Navigation Controller and I placed two buttons on my FirstViewController. Each of these buttons have a named identifier for the segue that in turn displays my SecondViewController in the UI of the iPhone application.
All works as expected, BUT, I would like to display in a label on the second view controller something as simple as 'You clicked Button 1'. I have tried placing this data manually in a NSMutableString variable that I declare in my AppDelegate, which I am able to reach in my second view controller but the value I assign to this is never displayed on the screen.
Apparently, a new instance of the SecondViewController is created and this might be why I am not seeing it. I have created an IBOutlet of type UILabel with a name, myLabel, to hold this value but alas, I see no change.
Any help would be greatly appreciated.
NOTE: I am happy to post code but I don't think it will really help with my question.
My solution in this situation is always a custom -init method. Such as,
-initWithButtonPressedString:(NSString*)message;
Declare that in the second view controller and call:
self.secondView = [[SecondViewController alloc]initWithButtonPressedString:#"some conditional string"];
Then, all that's required is an iVar in the second view controller to handle that passed string.
To pass data between view controllers you should consider
1. making a custom init for your view controller which passes in the additional information or
2. creating properties on your second view controller which you access from the first view controller.
You can create a property to the IBOutlet that you made but you need to make sure that if you access it from your first view controller that it is after the views are loaded.
It is hard to give you more direction without seeing your current code
Do you use Storyboards?
Anyways, have you connected IBOutlet to your variable in Interface Builder?
If you use Storyboards, you might try to use method called
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
ie.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"ChooseToDetailsSegue"]) {
preparedSegue = segue;
SaleDetailsViewController *saleDetailsVC = [preparedSegue destinationViewController];
saleDetailsVC.saleDetailsProduct = [elementsArray objectAtIndex:selectedRow];
saleDetailsVC.cardTransactionDetails = [[cardDetails alloc] init];
saleDetailsVC.cardTransactionDetails.number = infoCardNumber;
saleDetailsVC.cardTransactionDetails.month = infoExpiriationM;
saleDetailsVC.cardTransactionDetails.year = infoExpiriationY;
}
}
You just need to init new ViewController (your destination) and refer to their variables.
You can also use notifications. In the IBAction of the first button of your FirstViewController, you can add
NSNotification *messageFromFirstViewController = [NSNotification notificationWithName:#"firstbuttonMessage" object:#"You clicked Button 1"];
[[NSNotificationCenter defaultCenter] postNotification:messageFromFirstViewController];
and something similar for the IBAction of your second button.
In the viewDidLoad of your SecondViewController, you can then add
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(useNotification:) name:#"firstButtonMessage" object:nil];
Create the useNotification method to change your myLabel:
-(void) useNotification:(NSNotification *)notification {
self.myLabel.text = notification.object;}

Resources