Basically, I have two UIViewControllers, there are some buttons in one of them. Once the user touches the button in one of the View Controllers, I want to trigger some actions in another view controller. But it seems not working somehow. Basically, the "if" condition which is:
if (self.delegate && [self.delegate respondsToSelector:#selector(userDidTouchButtons:)])
{
[self.delegate userDidTouchButtons:self];
}
seems not working, because the [self.delegate respondToSelector]is always false.
This is the .h file of the first view controller, which has some buttons.
#import
#class RightSideMenuViewController;
#protocol RightSideMenuDelegate <NSObject>
- (void) userDidTouchButtons: (RightSideMenuViewController *) rightMenuViewController;
#end
#interface RightSideMenuViewController : UIViewController
#property (nonatomic, assign) id <RightSideMenuDelegate> delegate;
#end
This is the .m file of the first view controller.
- (IBAction)badmintonClicked:(UIButton *)sender
{
if (self.delegate && [self.delegate respondsToSelector:#selector(userDidTouchButtons:)])
{
[self.delegate userDidTouchButtons:self];
}
}
This is the .m file of the second view controller, where I want to trigger the action here, according to the buttons in the first view controller.
#import "RightSideMenuViewController.h"
#interface DiscoverTimelineTableViewController () <RightSideMenuDelegate>
#property (strong, nonatomic) RightSideMenuViewController *rightMeuViewController;
#end
- (void)viewDidLoad {
[super viewDidLoad];
self.rightMeuViewController.delegate = self;
}
#pragma mark - RIGHT MENU Delegate methods
- (void) userDidTouchButtons: (RightSideMenuViewController *) rightMenuViewController
{
NSLog(#"He touches me!!!");
}
Make sure that the delegate is properly set, i.e., self.rightMeuViewController should not be nil
it seems like you are not setting the rightMeuViewController property while navigating to second view controller
Related
I have UIView, what called Popup and poping from UIViewContorller(ParentVC)
On UIView I have 4 buttons. When buttons is pressed, it needs to open new Controllers from(ParentVC). I am using Delegate, were is my mistake?
//Popup.h
#protocol PopupDelegate
#required
- (IBAction)stepOfRestoration:(id)sender;
- (IBAction)clientCall:(id)sender;
- (IBAction)readyTo:(id)sender;
- (IBAction)givePhone:(id)sender;
#end
#interface Popup : PSCustomViewFromXib
#property (nonatomic, assign) id <PopupDelegate> delegate;
#property (strong, nonatomic) IBOutlet UIView *view;
- (IBAction)stepOfRestoration:(id)sender;
- (IBAction)clientCall:(id)sender;
- (IBAction)readyTo:(id)sender;
- (IBAction)givePhone:(id)sender;
In .m i have this:
#synthesize delegate;
....
- (IBAction)stepOfRestoration:(id)sender {
[self.delegate buttonPressed];
}
And this is Parent .m
...
CGRect rect = CGRectMake(0,0,200,300);
Popup *popup1 = [[Popup alloc] initWithFrame:rect];
popup1.delegate = self;
....
-(void)buttonPressed {
[self performSegueWithIdentifier:#"infoSegue" sender:nil];
}
So were is my mistake?
You don't have a method called buttonPressed in your protocol, you need to call a method in your protocol, e.g.
Popup.m
- (IBAction)buttonPressed:(id)sender {
[self.delegate stepOfRestoration:sender];
}
Parent.m
- (IBAction)stepOfRestoration:(id)sender {
// some code
}
Link to long winded but hopefully helpful tutorial, good luck.
In your Parent .m, you must conform all the methods which are defined in protocol. In your Parent.m file, buttonPressed method is not present in protocol. So update the name of below method with buttonPressed as follow:-
Update below code at Popup.h while declaring PopupDelegate methods
- (IBAction)stepOfRestoration:(id)sender;
With
-(void)buttonPressed;
you shouldn't add IBAction methods in your protocol
instead add following methods corresponding each button action
//Popup.h
#protocol PopupDelegate
#required
- (Void)stepOfRestoration:(id)sender;
- (Void)clientCall:(id)sender;
- (Void)readyTo:(id)sender;
- (Void)givePhone:(id)sender;
#end
and call these protocol methods in corresponding button action methods
e.g. //Popup.m
- (IBAction)stepOfRestoration:(id)sender {
[self.delegate stepOfRestoration:sender];
}
and //Parent.m
-(Void)stepOfRestoration:(id)sender{
// code here
}
I have a tableViewCell that says Nickname and when you click on it, a segue takes you to a view controller with a text field where you can type a nickname, once you push the back button it should appear in the detailTextLabel of the main table view controller. I just keep getting an error I posted the code below where I get an error as well.
nickname text field code:
#import "NicknameViewController.h"
#interface NicknameViewController ()
#end
#implementation NicknameViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self.delegate updateCarNickname:self.nicknameField];
}
#end
Here is the header file for the nickname view controller:
#import <UIKit/UIKit.h>
#protocol CarNicknameDelegate <NSObject>
#optional
- (void)updateCarNickname:(UITextField *)updateNickname;
#end
#interface NicknameViewController : UIViewController
#property (nonatomic, weak) id <CarNicknameDelegate> delegate;
#property (strong, nonatomic) IBOutlet UITextField *nicknameField;
#end
In the main view controller I keep getting errors on this code and can't seem to figure it out:
-(void)updateCarNickname:(UITextField *)updateNickname {
self.nicknameCell.detailTextLabel.text = updateNickname;
}
Before the segue begins I used this code:
if ([segue.identifier isEqualToString:#"nicknameSegue"]) {
NicknameViewController *controller = segue.destinationViewController;
controller.delegate = self;
}
All views in a view controller gets deallocated once the view controller's dealloc is called.
You should change your CarNicknameDelegate's parameter UITextField to NSString.
#protocol CarNicknameDelegate <NSObject>
#optional
- (void)updateCarNickname:(UITextField *)updateNickname;
#end
and change your NicknameViewController to something like this.
#interface NicknameViewController ()
#end
#implementation NicknameViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self.delegate updateCarNickname:self.nicknameField.text];
}
#end
I have an initial ViewController, lets call it HomeViewController, that has a button which calls a modal view controller, lets call it ModalViewController. Inside that ModalViewController I have a table view with two sections. If you click on any cell from section 0 it sends information back to HomeViewController (this part I have working with Protocol). If you click on any of the cells from section 1 it pushes to another view controller with options, lets call it OptionsViewController. Here is where it gets tricky for me. If you click any of those options, dismiss OptionsViewController and close ModalViewcontroller and send that information to HomeViewController, just like ModalViewController to HomeViewController. I have tried to set up a protocol similar to the one in ModalViewController but it is never called.
OptionsViewController protocol & .h file
#protocol OptionsViewControllerDelegate <NSObject>
#optional
-(void) optionsInfo:(NSArray *)optionsViewArray;
#end
#interface OptionsViewController : UITableViewController
#property (retain) id delegate;
#property (nonatomic, strong) NSArray *sendArray;
#end
OptionsViewController.m where it's called to pop off the stack.
{
[self dismissOptionsView];
}
-(void) viewWillDisappear:(BOOL)animated
{
NSLog(#"Send Array: %#", self.sendArray);
[[self delegate] optionsInfo:sendArray];
}
-(void)dismissOptionsView
{
[self.navigationController popViewControllerAnimated:YES];
}
Inside ModalViewController.h
#protocol ModalViewControllerDelegate <NSObject>
#optional
-(void) sendInformation:(NSArray *)infoArray;
#end
#interface ModalViewController : UITableViewController <ConditionsViewControllerDelegate, UISearchBarDelegate>
{
UISearchBar *searchDrugBar;
}
#property (retain) id delegate;
#property (nonatomic, strong) IBOutlet UISearchBar *searchDrugBar;
#property (nonatomic, strong) NSArray *infoArray;
#end
ModalViewController.m where OptionsInfo is supposed to come in.
-(void) optionsInfo:(NSArray *)optionsViewArray
{
//IT NEVER REACHES HERE :(
NSLog(#"HERE");
self.infoArray = optionsViewArray;
NSLog(#"Finished");
[self dismissViewControllerAnimated:YES completion:nil];
}
Has any one has done something similar like this or knows the solution to this? Any information, link, guidance and etc. to the right direction will be appreciated. Thanks in advance.
You need to set the delegate in your OptionsViewController below:-
In your OptionsViewController.m Include below line on your method
[self setDelegate:ModalViewController];
I ultimately want to write an iOS app incorporating ALAssetsLibrary, but as a first step toward understanding delegation, I'm trying to pass a simple message between two view controllers. For some reason, I can't seem to get the message to pass. In particular, the delegate object (derpy) doesn't appear to exist (if(self.derpy) returns NO)).
I asked the same question on the Apple forums and was told that I should be using segues and setting properties / calling methods using self.child instead, but that seems strange. If I were to pass messages using the parent / child properties, would I still be able to create my views in Interface Builder? Once I have my two views set up, say inside a UINavigationController, I'm not sure how to actually "wire them up" so I can pass messages between them. Sorry if the question is overly broad.
Here's the controller I'm declaring the protocol in (called PickerViewController):
Interface:
#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>
#protocol DerpDelegate <NSObject>
#required
- (void) test;
#end
#interface PickerViewController : UIViewController
#property (nonatomic, assign) id<DerpDelegate> derpy;
#end
Implementation:
#import "PickerViewController.h"
#interface PickerViewController ()
#end
#implementation PickerViewController
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.derpy) { // If the delegate object exists
[self.derpy test]; // send it this message
} else {
NSLog(#"Still not working."); // This always returns (i.e., self.derpy doesn't exist)
}
}
Delegate controller (MainViewController) interface:
#import <UIKit/UIKit.h>
#import "PickerViewController.h"
#interface MainViewController : UIViewController <DerpDelegate> // public promise to implement delegate methods
#property (strong, nonatomic) PickerViewController *picker;
- (void) test;
#end
And lastly, the delegate controller (MainViewController) implementation:
#import "MainViewController.h"
#import "PickerViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
// Here's that method I promised I'd implement
- (void) test{
NSLog(#"Test worked."); // This never gets called
}
- (void)viewDidLoad {
[super viewDidLoad];
self.picker.derpy = self;
//lazy instantiation
- (PickerViewController *) picker{
if(!_picker) _picker = [[PickerViewController alloc]init];
return _picker;
}
EDIT: Many thanks to rydgaze for pointing me in the right direction with self.picker.derpy = self, but for some reason, things still aren't working properly. Importantly, once that property has been set, if(self.picker.derpy) returns YES from MainViewController. But if(self.derpy) is still returning NO when called from inside the PickerViewController's viewDidLoad. How can the property exist and not exist at the same time?
You need to be sure that you're setting the delegate on the instance of the view controller that you put on screen. If you're using a navigation controller and segues to go between MainViewController and PickerViewController, then you should set the delegate in prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
self.picker = (PickerViewController *)segue.destinationViewController;
self.picker.derpy = self;
}
You need to populate the delegate first.
Basically, your MainViewController shoudl at somepoint do a
picker.derpy = self;
Then when the delegate fires in PickerViewController, the callback will happen.
Edit:
A good practice is to do something like in PickerViewController
#property (nonatomic, assign) id<DerpDelegate > derpy;
and in your MainViewController indicate that you will implement the delegate
#interface MainViewController : UIViewController<DerpDelegate>
Eventually in your implementation of MainViewController
You will have something like
picker = [[PickerViewController alloc]init];
picker.derpy = self;
[picker doYourThing];
Once picker is all done, it may want to return results using the delegate.
I am facing a problem related to delegation.I have 2 tabView. In first tabview i have 2 textfield and a button(to trigger the delegate method) and in the second tabview i have 2 label to display the content of textfield in the first tabview.Whats wrong with my code???
For first tabviewA the .h file
#import <UIKit/UIKit.h>
#class ViewControllerA;
#protocol ViewControllerADelegate <NSObject>
-(void)sayHello:(ViewControllerA*)viewController;
#end
#interface ViewControllerA : UIViewController<UITextFieldDelegate>
#property (nonatomic,strong)IBOutlet UITextField *textFieldFirst;
#property (nonatomic,strong)IBOutlet UITextField *textFieldSecond;
#property (nonatomic,strong)id<ViewControllerADelegate>delegate;
-(IBAction)next:(id)sender;
#end
and the .m file
#import "ViewControllerA.h"
#interface ViewControllerA ()
#end
#implementation ViewControllerA
#synthesize textFieldFirst=_textFieldFirst;
#synthesize textFieldSecond=_textFieldSecond;
#synthesize delegate=_delegate;
- (void)viewDidLoad
{
[super viewDidLoad];
_textFieldFirst.delegate=self;
_textFieldSecond.delegate=self;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return NO;
}
-(IBAction)next:(id)sender
{
[self.delegate sayHello:self];
}
#end
And for the second tabbarViewB the .h file
#import <UIKit/UIKit.h>
#import "ViewControllerA.h"
#interface ViewControllerB : UIViewController<ViewControllerADelegate>
#property (nonatomic,strong)IBOutlet UILabel *labelFirst;
#property (nonatomic,strong)IBOutlet UILabel *labelSecond;
#end
and the .m file
#import "ViewControllerB.h"
#interface ViewControllerB ()
#end
#implementation ViewControllerB
#synthesize labelFirst=_labelFirst;
#synthesize labelSecond=_labelSecond;
- (void)viewDidLoad
{
[super viewDidLoad];
ViewControllerA *viewControllerA=[self.tabBarController.viewControllers objectAtIndex:0];
viewControllerA.delegate=self;
// Do any additional setup after loading the view.
}
-(void)sayHello:(ViewControllerA *)viewController
{
_labelFirst.text=viewController.textFieldFirst.text;
_labelSecond.text=viewController.textFieldSecond.text;
}
#end
N.B: I have tried tabView B to tabview A with the same process and that worked fine. The reverse (i.e from A to B)is not working at all.Thanks
ViewControllerB sets itself as the delegate in its viewDidLoad method. This method is called as soon as the View Controller has loaded the view it manages (into its view property). That view is loaded only when someone tries to access the view controller's view property for the first time. See here. There's a good chance that ViewControllerB's view has not been loaded yet, so the viewDidLoad method has not been called yet.
If you override the awakeFromNib method like so:
(void) awakeFromNib {
[super awakeFromNib];
ViewControllerA *viewControllerA=[self.tabBarController.viewControllers
objectAtIndex:0];
viewControllerA.delegate = self;
}
it should work, since that method will be called when the view controller is initialized.