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!
Related
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;
}
}
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
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
i have problem with UIButton cancel of tableviewcontroller, when I do test, and I click the cancel button to call the action, he did not call the delegate, not work, follow code.
StalkViewController.
#import <UIKit/UIKit.h>
#import "FMDBDataAccess.h"
#import "EditStalkViewController.h"
#import "NewStalkViewController.h"
#interface StalkViewController : UITableViewController<NewStalkViewControllerDelegate>
#property (nonatomic,strong) NSMutableArray *stalks;
-(void)populateStalk;
#end
StalkViewController.m
-(void) addNewStalkViewControllerDidCancel:(NewStalkViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"addStalk"])
{
UINavigationController *navigationController = segue.destinationViewController;
NewStalkViewController *addNewStalkViewController = (NewStalkViewController *)[[navigationController viewControllers] objectAtIndex:0];
addNewStalkViewController.delegate = self;
}
}
NewStalkViewController.h
#import "Stalk.h"
#import "Utility.h"
#class NewStalkViewController;
#protocol NewStalkViewControllerDelegate<NSObject>
-(void) addNewStalkViewControllerDidCancel:(NewStalkViewController *)controller;
#end
#interface NewStalkViewController : UITableViewController<FBFriendPickerDelegate, UITextFieldDelegate>
{
}
#property (nonatomic,weak) id<NewStalkViewControllerDelegate> delegate;
- (IBAction)cancel:(id)sender;
#end
NewStalkViewController.m
#import "NewStalkViewController.h"
#implementation NewStalkViewController
#synthesize delegate;
-(IBAction)cancel:(id)sender
{
[self.delegate addNewStalkViewControllerDidCancel:self];
}
#end
help me!!
I have a table view controller segueing (with identifier feedToPollQuerySeg) to another view controller.
I am trying to print out the index number of the row selected in a label in the latter.
Feed View:
#interface FeedController3 : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, weak) IBOutlet UITableView* feedTableView;
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(NSString*)stringNum{
if([segue.identifier isEqualToString:#"feedToPollQuerySeg"]){
PollQueryController *pqc = [[PollQueryController alloc] init];
pqc = [segue destinationViewController];
NSLog(#"This is row sending: %#", stringNum);
pqc.parentRowSelected.text = stringNum;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSInteger rowSelected = indexPath.row;
NSString *stringNum = [NSString stringWithFormat:#"%d", rowSelected];
NSLog(#"This is row selected: %#", stringNum);
[self performSegueWithIdentifier: #"feedToPollQuerySeg" sender: stringNum];
}
PollQuery View
#interface PollQueryController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UILabel *parentRowSelected;
#implementation PollQueryController
#synthesize parentRowSelected;
-(void)viewDidLoad{
[super viewDidLoad];
NSLog(#"Parent Row Selected: %#", parentRowString);
...
}
But the label isn't updating...?
This is row selected: 1
This is row sending: 1
Parent Row Selected:
Its because when you are in prepareForSegue of FeedController3, PollQueryController's view isn't initialized.
Add NSString in PollQueryController set NSString value in prepareForSegue.
In viewWillAppear of PollQueryController assign text to parentRowSelected label.
Like This -
In the viewController that will present the another viewController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqual:#"feedToPollQuerySeg"])
{
PollQueryController *pvc = [segue destinationViewController];
pvc.myString = stringNum;
}
}
And inside the presented viewController:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.parentRowSelected.text = self.myString;
}
Here is a neater way to achieve what you want:
FeedController3.m:
#interface FeedController3
#property (nonatomic) int rowSelected;
#end
#implementation
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.rowSelected = indexPath.row;
NSLog(#"This is row selected: %#", [NSString stringWithFormat:#"%d", self.rowSelected]);
[self performSegueWithIdentifier:#"feedToPollQuerySeg" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"feedToPollQuerySeg"])
{
// Get reference to the destination view controller
PollQueryController *vc = [segue destinationViewController];
// Pass any objects to the view controller here, like...
vc.rowSelected = self.rowSelected;
}
}
#end
PollQueryController.h:
#interface PollQueryController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic) int rowSelected;
#property (weak, nonatomic) IBOutlet UILabel *parentRowSelected;
#end
PollQueryController.m:
#implementation
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.parentRowSelected.text = [NSString stringWithFormat:#"%d", self.rowSelected];
}
#end