AddBillViewController.h:
#protocol AddBillDelegate <NSObject>
- (void)addBillViewControllerDidAddOneBill;
#end
#interface AddBillViewController : UIViewController
#property (retain, nonatomic)id <AddBillDelegate> delegate;
#end
AddBillViewController.m:
- (IBAction)AddBill:(id)sender {
[self.delegate addBillViewControllerDidAddOneBill];
[self dismissViewControllerAnimated:YES completion:nil];
}
HomeViewController.m:
#interface HomeViewController () <AddBillDelegate>
#property (strong, nonatomic)AddBillViewController *abVC;
#end
#implementation HomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.abVC = [[AddBillViewController alloc] init];
self.abVC.delegate = self;
}
- (void)addBillViewControllerDidAddOneBill {
NSLog(#"Added a bill.");
}
#end
As you can see, there is button in AddBillViewController, when the button is pressed, addBill method will be called, then the delegate method addBillViewControllerDidAddOneBill in HomeViewController should be called, however in fact, it doesn't.
I think you are not getting the reference right here in this line
self.abVC = [[AddBillViewController alloc] init];
If you are performing a segue, like the AddBillViewController is your next controller, set delegate in performSegue: function
like
AddBillViewController *vc = [segue destinationViewController];
[vc setDelegate:self];
Related
I'm having trouble figuring out why I'm getting a nil delegate for this call. It seems like I'm setting the delegate just fine.
LogoutViewController.h
#protocol SomeNewDelegate <NSObject>
#required
- (void)someMethod;
#end
#interface LogoutViewController : UIViewController
#property (nonatomic, weak) id<SomeNewDelegate> delegate;
LogoutViewController.m
- (IBAction)logoutButtonTapped:(id)sender {
NSLog(#"logout tapped");
[self.delegate someMethod];
[self dismissViewControllerAnimated:YES completion:nil];
}
MainViewController.m
#interface MainViewController () <UIScrollViewDelegate, SomeNewDelegate>
#property (nonatomic, strong) LogoutViewController *logoutVC;
#end
#implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.logoutVC.delegate = self;
}
- (void)someMethod {
NSLog(#"someMethod");
}
someMethod never gets called and I don't see why the delegate is nil. Any help?
Use below code in viewDidload
LogoutViewController *logoutVC = [[LogoutViewController alloc]init];
logoutVC.delegate = self;
Remove LogoutViewController from property.
I have used this and its working fine.
Hope its working for you.
Edited code in .h file
#protocol syncDataDelegate <NSObject>
#required
- (void) offlineSyncProcess;
#end
#interface LoginViewController : UIViewController
{
id <syncDataDelegate> syncDelegate;
}
#property (retain) id syncDelegate;
in .m file
#implementation LoginViewController
{
// your code
}
#synthesize syncDelegate;
- (IBAction)logoutButtonTapped:(id)sender {
NSLog(#"logout tapped");
[syncDelegate offlineSyncProcess];
}
You can call delegate method from here in LoginViewController.m file from any method.
in My Delegate implementation
in .m file
#interface MainViewController ()<syncDataDelegate>
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
LoginViewController *LVC = [[LoginViewController alloc]init];
LVC.syncDelegate = self;
}
now use the delegate methode here
- (void) offlineSyncProcess
{
// your code here
}
this code is working in my project, check this in your project.
Make sure your logoutVC is not nil when you try to set the delegate property for it.
You can implement the setDelegate method in your LogoutViewController.m. Then use break point to make sure it is invoked.
Delegate is nil because your logoutVC is nil, you haven't allocated memory to the logoutvc property.
Just before self.logoutVC.delegate = self
Add following code
self.logoutVC = [[LogoutViewController alloc]init];
Everything will start working automatically.
I have a controller that gets instantiated and pushed onto the navigation controller like this -
In ParentVC.m
ThingContainerViewController *thingContainer = [[ThingContainerViewController alloc] init];
thingContainer.delegate = self;
[self.navigationController pushViewController:thingContainer animated:YES];
Now I want to send back a value to ParentVC when the thingContainer is closed. So I have implemented a delegate as follows:
in ParentVC.h
#interface ParentVC : UIViewController <..., ThingContainerViewControllerDelegate>
in ThingContainer.h
#protocol ThingContainerViewControllerDelegate <NSObject>
- (void)addItemViewController:(id)controller didFinishEnteringItem:(NSInteger)page;
#end
....
#interface
....
#property (nonatomic, weak) id <ThingContainerViewControllerDelegate> delegate;
....
#end
in ParentVC.m
- (void)addItemViewController:(id)controller didFinishEnteringItem:(NSInteger)page {
self.page = page;
}
in ThingContainer.m
- (IBOutlet) ... closeButtonWasTapped:(UIButton *)button {
NSLog(#"%ld", (long)indexOfPage);
[self.delegate addItemViewController:self didFinishEnteringItem:indexOfPage];
[[self navigationController] popViewControllerAnimated: YES];
}
At this point, self.delegate is null, so the method in the ParentVC never gets called. Any idea how I can fix it?
I'm just starting to learn Objective-C and I'm not 100% on all the syntax yet, and I think that might be where I'm having trouble, then again I'm not sure. I'm trying to get one view controller to send a message to its parent/callee view controller. I have it set up like this:
//ParentViewController.h
#import "SubViewController.h"
#interface ParentViewController : UIViewController <SubViewControllerDelegate>
- (void) sendMessageToParent:(NSInteger)num;
#end
This is the implementation:
//ParentViewController.m
#implementation ParentViewController
- (void) sendMessageToParent:(NSInteger)num
{
NSLog(#"Message is %d", num);
}
- (void) buttonPushed
{
[self performSegueWithIdentifier:#"SubView" sender:sender];
}
#end
Here's the other view controller setup:
//SubViewController.h
#protocol SubViewControllerDelegate <NSObject>
- (void) sendMessageToParent:(NSInteger)num;
#end
#interface SubViewController : UIViewController
#property (nonatomic, weak) id <SubViewController> delegate;
#end
And implementation:
//SubViewController.m
#implementation SubViewController
#synthesize delegate;
- (void) something
{
[self.delegate sendMessageToParent:4];
[self.dismissViewControllerAnimated:YES completion:nil];
}
Appreciate any help, thanks.
You need to add to ParentViewController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"SubView"])
{
SubViewController *vc = [segue destinationViewController];
vc.delegate = self;
}
}
You need to add handler for prepareForSegue and set .delegate properly there. I don't think your SubviewController has delegate set to the parent one.
Looks like you're not setting SubViewController's delegate to SuperViewController. You'd do this typically when you instantiate SubViewController. e.g. subViewController.delegate = self
ParentViewController.h
#interface ParentViewController : UIViewController
#end
ParentViewController.m
#implementation ParentViewController <SubViewControllerDelegate> // Better to place this in .m than .h
#pragma mark - SubViewController Delegate
- (void)sendMessageToParent:(NSInteger)num
{
NSLog(#"Message is %d", num);
}
- (void)buttonPushed
{
[self performSegueWithIdentifier:#"SubView" sender:sender];
}
#end
SubViewController.h
#protocol SubViewControllerDelegate <NSObject>
- (void)sendMessageToParent:(NSInteger)num;
#end
#interface SubViewController : UIViewController
#property (nonatomic, weak) id<SubViewController> delegate;
#end
SubViewController.m
#implementation SubViewController
// #synthesize delegate; // Not necessary, old fashioned
- (void)something
{
// Set a breakpoint here and step through, you're not setting your delegate, so this conditional is not being hit
if (self.delegate && [self.delegate respondsToSelector:#selector(sendMessageToParent:)])
{
[self.delegate sendMessageToParent:4];
}
[self.dismissViewControllerAnimated:YES completion:nil];
}
I have a VC of custom type LVSBBSettingsViewController for user settings. The VC is presented by a main menu in LVSMainViewController. The main VC sets the values of the controls in the settings VC programatically. However, when the settings view appears, the controls all revert to the values assigned to them in the storyboard.
I am using delegation to close the settings view and to pass data from the settings VC back to the main VC when it closes. But I don't think that's what's causing the problem since the same thing happens even if I remove that.
What's causing this? I have a feeling I'm missing something really simple here...
LVSBBSettingsViewController.h:
#import <UIKit/UIKit.h>
#class LVSBBSettingsViewController;
#pragma mark LVSBBSettingsViewController Delegate
#protocol LVSBBSettingsViewControllerDelegate <NSObject>
- (void)settingsViewControllerDidCancel:(LVSBBSettingsViewController *)controller;
- (void)settingsViewControllerDidSave:(LVSBBSettingsViewController *)controller;
#end
#pragma mark LVSBBSettingsViewController
#interface LVSBBSettingsViewController : UITableViewController
#property (nonatomic, weak) id <LVSBBSettingsViewControllerDelegate> delegate;
#property (weak, nonatomic) IBOutlet UISwitch *showBranchVarLabelsSwitch;
#property (weak, nonatomic) IBOutlet UISwitch *useAnimationSwitch;
#property (weak, nonatomic) IBOutlet UISwitch *showAllNodesSwitch;
#property (weak, nonatomic) IBOutlet UILabel *tempLabel;
- (IBAction)cancel:(id)sender;
- (IBAction)done:(id)sender;
#end
LVSBBSettingsViewController.m:
#import "LVSBBSettingsViewController.h"
#interface LVSBBSettingsViewController ()
#end
#implementation LVSBBSettingsViewController
// ... Xcode-generated stuff ...
- (IBAction)cancel:(id)sender
{
[self.delegate settingsViewControllerDidCancel:self];
}
- (IBAction)done:(id)sender
{
[self.delegate settingsViewControllerDidSave:self];
}
#end
LVSBBMainViewController.h:
#import <UIKit/UIKit.h>
#import "LVSBBSettingsViewController.h"
#interface LVSMainViewController : UIViewController <LVSBBSettingsViewControllerDelegate>
#end
LVSBBMainViewController.m:
#import "LVSMainViewController.h"
#import "LVSBBMasterViewController.h"
#interface LVSMainViewController ()
#end
#implementation LVSMainViewController
{
LVSBBMasterViewController *bbmvc;
}
// ...
- (void)viewDidLoad
{
[super viewDidLoad];
// Get main storyboard
UIStoryboard *st = [UIStoryboard storyboardWithName:[[NSBundle mainBundle].infoDictionary objectForKey:#"UIMainStoryboardFile"] bundle:[NSBundle mainBundle]];
// Instantiate bbmvc
bbmvc = [st instantiateViewControllerWithIdentifier:#"BBMasterViewControllerStoryboard"];
// Initialize settings
bbmvc.showBranchVarLabels = YES;
bbmvc.useAnimation = YES;
bbmvc.showAllNodes = NO;
}
...
#pragma mark LVSBBSettingsViewController Delegate
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ShowSettings"])
{
// Get pointer to settings VC
UINavigationController *navigationController = segue.destinationViewController;
LVSBBSettingsViewController *settingsViewController = [navigationController viewControllers][0];
// Set delegate
settingsViewController.delegate = self;
// Populate settings VC
// (same problem occurs if I replace right-hand sides of next 3 lines with NO;)
settingsViewController.showBranchVarLabelsSwitch.on = bbmvc.showBranchVarLabels;
settingsViewController.useAnimationSwitch.on = bbmvc.useAnimation;
settingsViewController.showAllNodesSwitch.on = bbmvc.showAllNodes;
settingsViewController.tempLabel.text = #"HELLO";
}
}
- (void)settingsViewControllerDidCancel:(LVSBBSettingsViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)settingsViewControllerDidSave:(LVSBBSettingsViewController *)controller
{
// Set settings in bbmvc
bbmvc.showBranchVarLabels = controller.showBranchVarLabelsSwitch.on;
bbmvc.useAnimation = controller.useAnimationSwitch.on;
bbmvc.showAllNodes = controller.showAllNodesSwitch.on;
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
UPDATE: As a workaround, I added properties in LVSBBSettingsViewController that match the properties in LVSMainViewController. In prepareForSegue:sender:, I set those properties instead of setting the controls directly. Then in viewDidLoad in LVSBBSettingsViewController, I set the control values based on the properties. This seems to work. Still not sure why I can't set the control values directly, though.
I am trying to segue to another screen from a uitableview in iOS5. I have set up a delegate etc. which seems to work (the segue occurs) but I think I need to "set delegate to initialize the data I want to display in the new screen. I get a NSInvalidArgumentException error though when I call it is prepareforsegue.
Here is the code for the uitableview part...
#import "iTanksV2ListViewController.h"
#import "tank.h"
#import "tankDetailViewController.h"
#interface iTanksV2ListViewController ()
#property tank *selectedTank;
#end
#implementation iTanksV2ListViewController
#synthesize tanks = _tanks;
#synthesize tankTableView = _tankTableView;
#synthesize delegate = _delegate;
#synthesize selectedTank = _selectedTank;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.tankTableView.delegate = self;
self.tankTableView.dataSource = self;
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"Show Tank Details"])
{
UILabel *myLabel = [[UILabel alloc] init];
myLabel.text = self.selectedTank.tankNumber;
[segue.destinationViewController setTankNumberLabel:myLabel];
[segue.destinationViewController setDelegate:self]; ///this is where it fails!!!
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedTank = [self.tanks objectAtIndex:indexPath.row];
[self.delegate iTanksListViewController:self choseTank:self.selectedTank];
}
and then in the detail view I use the following...
-(void)iTanksListViewController:(iTanksV2ListViewController *)sender choseTank:(id)tank
{
self.tankToShow = tank;
}
but this doesn't get called - presumably because i don't successfully call the setdelegate method?!
You must not have synthesized your delegate property. Also, make sure that your header file properly has the delegate protocol referenced like
#interface TankDetailViewController : UITableViewController <DELEGATEPROTOCOL>
I thought I had... this snippet is from the itanksv2listviewcontroller header:
#interface iTanksV2ListViewController : UITableViewController
#property (nonatomic, strong) NSArray *tanks;
#property (weak, nonatomic) IBOutlet UITableView *tankTableView;
#property (weak, nonatomic) id <iTanksV2ListViewControllerDelegate> delegate;
#end
and this from the m file :
#synthesize delegate = _delegate;
and this is what I have put in the detailview m file:
#interface tankDetailViewController () <iTanksV2ListViewControllerDelegate>
#end