Custom Delegate method is not getting called - ios

I have set up custom delegate as follows, but delegate method is not getting called. I wonder what I am missing in my following implementation.
ComboSetViewController.h
#protocol ComboSetViewControllerDelegate <NSObject>
#required
- (void)comboSelected;
#end
#interface ComboViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#property (nonatomic, weak) id <ComboSetViewControllerDelegate> comboSelectedDelegate;
#end
ComboSetViewController.m
- (IBAction)doneBtnClicked
{
selectedCombo.orderProductItemArray = comboOrderItemArray;
[comboSelectedDelegate comboSelected];
[self dismissViewControllerAnimated:YES completion:nil];
}
HomeViewController.h
#import "ComboViewController.h"
#interface HomeViewController : UIViewController<ComboSetViewControllerDelegate>
HomeViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
ComboViewController *comboViewController = [[ComboViewController alloc] init];
comboViewController.comboSelectedDelegate = self;
}
// is not getting called
-(void)comboSelected
{
NSLog(#"Combo Selected");
}
EDIT: If I assign the delegate in the prepareSegue, then it works.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"isCombo"])
{
ComboViewController *vc = [segue destinationViewController];
// Assign self as the delegate for the child view controller
vc.comboSelectedDelegate = self;
}
}

Related

Delegate not responding to selector

I want to pass a NSInteger from a tableViewController (HistoryTableViewController) to another viewController (InformationViewController) but apparently it is not responding to my selector.
HistoryTableViewController.h:
#class HistoryTableViewController;
#protocol HistoryTableViewControllerDelegate <NSObject>
- (void)addItemViewController:(HistoryTableViewController *)controller passItem:(NSInteger *)rowNum;
#end
#interface HistoryTableViewController : UITableViewController {
NSInteger row;
}
#property (nonatomic, weak) id <HistoryTableViewControllerDelegate> delegate;
#end
HistoryTableViewController.h
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
row = [self.tableView indexPathForSelectedRow].row;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"informationSegue"]) {
if([self.delegate respondsToSelector:#selector(addItemViewController:passItem:)]){
[self.delegate addItemViewController:self passItem:&(row)];
}
}
}
InformationViewController.h:
#interface InformationViewController : UIViewController <HistoryTableViewControllerDelegate>
#property (nonatomic, assign) NSInteger rowIn;
InformationViewController.m
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"informationSegue"]) {
HistoryTableViewController *historyvc = segue.destinationViewController;
historyvc.delegate = self;
}
}
- (void) addItemViewController:(HistoryTableViewController *)controller passItem:(NSInteger *)rowNum {
rowIn = *rowNum;
}
"informationSegue" is my segueIdentifier to go from HistoryTableViewController to InformationViewController.
I actually found out the answer myself. I was using the code for passing the delegate back to another view controller, but I was supposed to pass the delegate forward between view controllers

Delegate not responds to selector

Basically, I am now intend to use delegate to pass values between view controllers.
The flow of the view controllers is A -> B -> C using push segue.
When the user does some action in the "C" view controller, how to pass the value BACK to the first view controller, which is "A"?
In my code, "self.delegate" is always nil and the delegate method is never triggered.
Below is the code of the First VC and Third VC:
First VC .m:
#import "ViewController.h"
#import "ThirdViewController.h"
#interface ViewController ()<PassValueProtocal>
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
#end
#implementation ViewController
{
ThirdViewController *thirdVC;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void) passValueBack:(NSString *)value
{
NSLog(#"HAHAH");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)segueToSecondVC:(UIButton *)sender
{
thirdVC = [ThirdViewController sharedManager];
thirdVC.delegate = self;
}
#end
Third VC .h:
#import <UIKit/UIKit.h>
#protocol PassValueProtocal <NSObject>
- (void) passValueBack: (NSString *) value;
#end
#interface ThirdViewController : UIViewController
#property (weak, nonatomic) id<PassValueProtocal>delegate;
+ (id) sharedManager;
#end
Third VC .m:
#import "ThirdViewController.h"
#interface ThirdViewController ()
#property (weak, nonatomic) IBOutlet UITextField *myTextField;
#end
#implementation ThirdViewController
+ (id) sharedManager
{
NSLog(#"myDelegate sharedManager");
static ThirdViewController *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ sharedManager = [[self alloc] init]; });
return sharedManager;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)passValueAction:(UIButton *)sender
{
NSLog(#"%#", self.delegate);
if ([self.delegate respondsToSelector:#selector(passValueBack:)])
{
[self.delegate passValueBack:self.myTextField.text];
}
}
#end
Your code
- (IBAction)segueToSecondVC:(UIButton *)sender
{
thirdVC = [ThirdViewController sharedManager];
thirdVC.delegate = self;
}
Should not be here. You should implement function prepareForSegue and move this code there. Something like
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
ThirdViewController *thirdVC = (ThirdViewController *)segue.destinationViewController;
thirdVC.delegate = self;
}

Cannot reference delegate protocols in implimentation

I have a UIViewController with a UIPickerView that creates a string that I want to pass along to my RootViewController (BL_MainViewController).
My tactic was to use the delegate pattern but I can't figure out where I'm going wrong here. If my RootViewController is created using a Storyboard, how do I tell it BL_MainViewController.BL_SetTimerViewController = self and where do I set that in the implementation (guess:ViewDidLoad)?
BL_SetTimerViewController.h (the child VC presented by modal segue in IB)
#protocol BL_SetTimerViewControllerDelegate
-(void) updateLabelWithString:(NSString *)string;
#end
#interface BL_SetTimerViewController : UIViewController{
... // some ivars
}
#property (assign, nonatomic) id <BL_SetTimerViewControllerDelegate> delegate;
#end
BL_SetTimerViewController.m
#implementation BL_SetTimerViewController
...
#synthesize delegate;
...
- (IBAction)setTimerAndDismissViewController:(id)sender {
// does some stuff, then:
[self.delegate updateLabelWithString:#"TEST"];
[self dismissViewControllerAnimated:YES completion:nil];
}
BL_MainViewController.h (The Root VC)
#import "BL_SetTimerViewController.h"
#interface BL_MainViewController : UIViewController <BL_SetTimerViewControllerDelegate>{
...
}
#end
BL_MainViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// do some stuff here
// presumably also assign the delegate protocol?
}
-(void)updateLabelWithString:(NSString *)string {
self.pLabel.text = string;
}
In your BL_MainViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.pLabel.text=GlobleSting;
}
-(void)updateLabelWithString:(NSString *)string {
GlobleSting = string; //declare in .h file
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"YoursegueIdentifir"]) {
BL_SetTimerViewController *settimerVC =
segue.destinationViewController;
settimerVC.delegate = self;
}
}
Super simple test app for delegate(note that many thing are left out as it's quickly thrown together), this works for me.(note that delegate is weak, not assign. If you are targeting iOS 5+, use weak for delegates)
SimpleProtocol.h
#protocol SimpleProtocol <NSObject>
- (void)updateText:(NSString *)text;
#end
ViewController.m
#import "ViewController.h"
#import "SecondViewController.h"
#import "SimpleProtocol.h"
#interface ViewController ()<SimpleProtocol>
#property (nonatomic, weak) IBOutlet UILabel *label;
#end
#implementation ViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SecondViewController *vc = (SecondViewController *)segue.destinationViewController;
vc.delegate = self;
}
- (void)updateText:(NSString *)text
{
self.label.text = text;
}
#end
SecondViewController.m
#import "SimpleProtocol.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[NSTimer scheduledTimerWithTimeInterval:3 target:self selector:#selector(timerFire:) userInfo:nil repeats:NO];
}
- (void)timerFire:(NSTimer *)timer
{
NSString *text = [NSString stringWithFormat:#"Test %#", #(arc4random())];
[self.delegate updateText:text];
[self.navigationController popViewControllerAnimated:YES];
}
#end

trying to learn objective-c delegates. why wont my sample project work?

I am trying to pass data between two view controllers. viewcontroller2 is a delegate of viewcontroller.. note.. i called the delegate property "homie" yes I know this is bad practice but I am just messing around trying to understand the concept.
here is viewcontroller:
#import <UIKit/UIKit.h>
#protocol ViewControllerDelegate <NSObject>
#required
- (void)sendData:(NSString *)theString;
#end
#interface ViewController : UIViewController
#property (nonatomic, assign) id <ViewControllerDelegate> homie;
- (void)doSomething;
- (IBAction)doneText:(id)sender;
#end
implementation:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)doSomething{
}
- (IBAction)doneText:(id)sender {
UITextField *thisField = sender;
if([_homie respondsToSelector:#selector(sendData:)]){
[_homie sendData:[thisField text]];
}
}
now here is the other view controller implementing the first
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface ViewController2 : UIViewController <ViewControllerDelegate>
- (IBAction)hittingbtn:(id)sender;
#property (weak, nonatomic) IBOutlet UITextField *textfield;
#property (strong, nonatomic) ViewController *vc;
#end
implementation:
#import "ViewController2.h"
#interface ViewController2 ()
#end
#implementation ViewController2
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
ViewController *theview = [[ViewController alloc]init];
theview.homie = self;
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// DELEGATE METHOD
- (void)sendData:(NSString *)theString{
[_textfield setText:theString];
}
- (IBAction)hittingbtn:(id)sender {
}
#end
in viewdidload I instantiate the first viewcontroller, and set myself as its delegate. im assuming then when that viewcontroller2 runs the code in its method then it will see if its delegate has implemented the delegate method and use that code.. what am i missing here?
Your problem is that you use ViewControllers wrong. You have initialized ViewController
ViewController *theview = [[ViewController alloc]init];
theview.homie = self;
And what next? You haven't assign it to your properties or something. What have you do? It's simple. You have to implement - (void)prepareForSegue:sender:. First of all in your storyboard set segue's identifier. Then do following.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"MySegue"]) {
ViewController *destinationViewController = (ViewController *)[segue destinationViewController];
ViewController.homie = self;
}
}
You need to set the delegate in prepareForSegue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController respondsToSelector:#selector(setHomie)]) {
[segue.destinationViewController setHomie:self];
//or
if ([[segue.destinationViewController isKindOfClass:[ViewController class]]) {
ViewController *destinationViewController = (ViewController *)[segue destinationViewController];
ViewController.homie = self;
}
//or the segue identifier which has already been mentioned
}

methods from a protocol is not called

I got the next problem I have 3 views (a UITableView, and2 View Controller) I made the next 2 protocols : AddViewControllerDelegate and ViewAlarmControllerDelegate:
AddViewController.h :
#protocol AddViewControllerDelegate <NSObject>
- (void)addAlarm:(AlarmObject *)alarm;
#end
#interface AddViewController : UIViewController
{
id <AddViewControllerDelegate> delegate;
}
#property (retain) id delegate;
ViewAlarmController.h:
#protocol ViewAlarmControllerDelegate <NSObject>
- (void)changeAlarm:(AlarmObject *)alarm atIndex:(int) alarmID;
- (void)deleteAlarmAtIndex:(int) alarmID;
#end
#interface ViewAlarmController : UIViewController
{
id <ViewAlarmControllerDelegate> delegate;
}
#property (retain) id delegate;
Then in HomeViewController.h I imported as fallow:
#import "AddViewController.h"
#import "ViewAlarmController.h"
#import "AlarmObject.h"
#interface HomeViewController : UITableViewController <AddViewControllerDelegate, ViewAlarmControllerDelegate>
And I have the next declaration of methods into HomeViewController.m
- (void)addAlarm:(AlarmObject *)alarm{
[self.items addObject:alarm];
[self.tableView reloadData];
NSLog (#"added");
}
- (void)deleteAlarmAtIndex:(int)alarmID{
NSLog(#"alarmID: %d", alarmID);
[self.items removeObjectAtIndex:alarmID];
NSLog(#"items: %#", items);
[self.tableView reloadData];
}
- (void)changeAlarm:(AlarmObject *)alarm atIndex:(int)alarmID{
NSLog(#"change");
}
ViewAlarmController.m the calling of protocol's method code block:
- (IBAction)save:(id)sender {
AlarmObject* alarmObj = [[AlarmObject alloc]init];
if(![self.alarmNameField.text isEqual: #""]){
[alarmObj setValue:self.alarmNameField.text forKey:#"alarmName"];
NSLog (#"change alarm id = %d", alarmID);
[self.delegate changeAlarm:alarmObj atIndex:alarmID];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)reverse:(id)sender {
alarmNameField.text = [alarm valueForKey:#"alarmName"];
}
- (IBAction)deleteAlarm:(id)sender {
NSLog (#"delete alarm id: %d",alarmID);
[self.delegate deleteAlarmAtIndex:alarmID];
[self dismissViewControllerAnimated:YES completion:nil];
}
The problem is that the addAlarm works but when i go into ViewAlarm and i press the button to delete or save the changes the deleteAlarmAtIndex and changeAlarm methods are not called.
The problem was in the next method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"addAlarmSegue"]){
AddViewController *avc = segue.destinationViewController;
avc.delegate = self;
}else if ([segue.identifier isEqualToString:#"viewAlarmSegue"]){
NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
ViewAlarmController *vac = segue.destinationViewController;
[vac getObject:[self.items objectAtIndex:selectedRowIndex.row] withId:selectedRowIndex.row];
vac.delegate = self;
}
}
I didn't wrote vac.delegate = self;
Make sure that object which should conforms to your protocol is not nil
My1Object *a = [My1Object new];
My2Object <Myprotocol> *b = [My2Object new];
a.delegate = b;
#interface My1Object <MyProtocol>
#property (nonatomic, weak /* or 'unsafe_unretained' for iOS less than 5.0*/) id <MyProtocol> delegate;
#end
#implementation My1Object
...
- (void)somethingHappened {
// just for check as I said:
NSLog(#"self.delegate = %#", self.delegate); // make sure this is not nil!
if ([self.delegate respondsToSelector:#selector(myProtocolMethod:)]) {
[self.delegate myProtocolMethod:self];
}
}
...
#end
Remember that you shouldn't retain (strong) your delegate!

Resources