I have two ViewControllers: A and B,
I am computing variable of B in A and then pushing B with its variable value by creating object of ViewController B. Variable of B is declare in itself. Now I am changing value of variable in ViewController B and return back to the A. I want to use Changed value of variable in A. I have tried protocol for this but in A I am getting 0 value of that variable.
Here is my code:
ViewController A.h
#import <UIKit/UIKit.h>
#import "B.h"
#class B;
#interface ViewController : UIViewController<nxtDelegate>
{
int vcheck;
}
#property(nonatomic,assign) int vcheck;
Implementation of A:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize lbl,txt,vcheck;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)viewWillAppear:(BOOL)animated{
NSLog(#"vcheckis:%d",vcheck);
}
-(void)chngvalue:(int)i{
vcheck=i;
}
ViewController B.h
#import <UIKit/UIKit.h>
#protocol nxtDelegate <NSObject>
-(void)chngvalue:(int )i;
#end
#interface nextviewController : UIViewController<UITableViewDelegate,UIPickerViewDelegate,UIPickerViewDataSource>
{
int chcek;
}
#property(weak,nonatomic)id<nxtDelegate> delegate;
- (IBAction)btnclick:(id)sender;
#property(nonatomic,assign) int chcek;
ViewController B.m
- (IBAction)chngAction:(id)sender {
[_delegate chngvalue:chcek];
NSLog(#"%#",_delegate);}
I don't know why it's not working but I just do the below and it's work fine for me
#property(nonatomic, assign)id<nxtDelegate> Delegate;
synthesize the property name Delegate
#synthesize Delegate;
and during push I set the delegate
ViewControllerB *ViewControllerBObj=[[ViewControllerB alloc] init];
[ViewControllerBObj setDelegate:self];
[[self navigationController] pushViewController:ViewControllerBObj animated:YES];
In IBAction
- (IBAction)chngAction:(id)sender
{
if([[self Delegate] respondsToSelector:#selector(chngvalue:)])
[[self Delegate] chngvalue:chcek];
}
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 simple example:
NavViewController
ViewController
ViewController2
In ViewController:
#import "ViewController.h"
#import "ViewController2.h"
#interface ViewController ()
#end
NSArray *array;// Neither in #interface nor in #implementation
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
array = [[NSArray alloc] initWithObjects:#"12345", nil];
ViewController2 *vc = [[ViewController2 alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
In ViewConroller2:
#import "ViewController2.h"
#interface ViewController2 ()
#end
NSArray *array;
#implementation ViewController2
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%#",array);
}
I don't understand why my array in viewController2 passed data from viewController?
Can explain this?
Guys I know how pass data to another viewController with property. I want to understand why, in this case, the data is transferred!
Because you've declared NSArray *array; as a Global variable. And, as long as the variable is defined somewhere in a source file, the linker will be able to find it and appropriately link all the references in other source files to the definition.
we also declare global variables using extern
extern int GlobalVar;
Here, externtells the compiler that this is just a declaration that an object of type int identified by GlobalVar exists and linker's job to ensure.
In one of your source file, you could say
int GlobalVar = 7;
I believe this is the reason in your case.
When you declare your variable outside #interface or #implementation it is considered to be static variable hence it worked. keep it inside would not work.
#interface ViewController ()
{
NSArray *array;
}
#end
try this instead of your code
I'm trying to separate the UITextViewDelegate methods from the main class of my project, I created a class to manage the delegate methods, but I can not change the values of the IBOulets from the main class.
I made a test project with a ViewController and a TextFieldController, in the Storyboard I add a text field and a label. What I want to do is change the text of the label when I start to write in the text field. Here is the code:
ViewController.h:
#import <UIKit/UIKit.h>
#import "TextFieldController.h"
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UITextField *textField;
#property (strong, nonatomic) IBOutlet UILabel *charactersLabel;
#end
ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) TextFieldController *textFieldController;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_textFieldController = [[TextFieldController alloc] init];
_textField.delegate = _textFieldController;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
TextFieldController.h:
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface TextFieldController : UIViewController <UITextFieldDelegate>
#end
Text Field Controller.m:
#import "TextFieldController.h"
#interface TextFieldController ()
#property ViewController *viewController;
#end
#implementation TextFieldController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL) textFieldShouldBeginEditing:(UITextField *)textField {
NSLog(#"hello");
_viewController.charactersLabel.text = #"hello";
return YES;
}
#end
When I start writing in the text field the message "Hello" is printed in the log, but the text of the label does not change. I want to know how to change the label text value from the other class.
First change the TextFieldController.h like this:
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface TextFieldController : NSObject <UITextFieldDelegate>
{
}
#property (nonatomic, assign) ViewController *viewController;
#end
Then change your TextFieldController.m file like this:
#import "TextFieldController.h"
#interface TextFieldController ()
#end
#implementation TextFieldController
- (BOOL) textFieldShouldBeginEditing:(UITextField *)textField {
NSLog(#"hello");
self.viewController.charactersLabel.text = #"hello";
return YES;
}
#end
In the ViewController.m do like that:
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) TextFieldController *textFieldController;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_textFieldController = [[TextFieldController alloc] init];
_textFieldController.viewController = self;
_textField.delegate = _textFieldController;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
This will work but I personally dont like that way you took.
Good luck :)
It's failing because _viewController is nil. You need to assign the viewController property in your delegate in order to support the two way communication.
Also, I'd strongly recommend you make your delegate object a subclass of NSObject, and not UIViewController. It does nothing with controlling views. You can just manually instantiate it in your ViewController objects viewDidLoad.
In TextViewController I don't see where the viewController property (_viewController ivar) is being set so it is probably nil. You should set it when you create the TextViewController instance.
When you are navigating to other controllers using storyboad's segue then you need to implement prepareForSegue method to initialised its properties as follows
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"segue for textFieldController"])
{
TextFieldController *_textFieldController = [segue destinationViewController];
_textField.delegate = _textFieldController;
}
}
But I was wondering, why are you setting textFieldDelegate here, why can't you set in TextFieldController's viewDidLoad method as then you didn't you to implement above prepareForSegue method call?
Besides you are keeping strong reference of each other and you are creating strong retain cycle.
One more thing, following code
_textField.delegate = _textFieldController;
will not work, until textFieldController is loaded and its viewDidLoad method is being called as you are only initialising it but its outlets will not be connected until view is loaded into navigation stack.
I created a new tabbed view project in Xcode in firstViewController I created a protocol like this
#protocol myProtocol <NSObject>
-(void)myProtocolMethodOne;
#end
#interface FirstViewController : UIViewController
#property (weak) id<myProtocol> mypDelegate;
- (IBAction)button1Tap:(id)sender;
#end
In .m file I did this
#synthesize mypDelegate;
.
.
.
- (IBAction)button1Tap:(id)sender
{
[mypDelegate myProtocolMethodOne];
}
This is secondViewController .h file
#interface SecondViewController : UIViewController <myProtocol>
#property (strong) FirstViewController *fvc;
#end
This is .m file
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Second", #"Second");
self.tabBarItem.image = [UIImage imageNamed:#"second"];
_fvc = [[FirstViewController alloc]init];
[_fvc setMypDelegate:self];
}
return self;
}
-(void)myProtocolMethodOne
{
NSLog(#"2nd VC");
[[self tabBarItem]setBadgeValue:#"ok"];
}
myProtocolMethodOne is not working, what I did wrong?
_fvc = [[FirstViewController alloc]init];
[_fvc setMypDelegate:self];
You're setting the delegate to a completely new FirstViewController, but not the one who trigger your method - (IBAction)button1Tap:(id)sender
You have to pass your delegate when you're doing the transition between your 2 view controllers, for example in - prepareForSegue: or when you doing [self.navigationController pushViewController:vc animated:YES]
Here is Best site with source code for learn basic about protocol.
////// .h file
#import <Foundation/Foundation.h>
#protocol myProtocol <NSObject>
#required
-(void)myProtocolMethodOne;
#end
#interface FirstViewController : UIViewController
{
id <myProtocol> mypDelegate;
}
#property (retain) id mypDelegate;
- (IBAction)button1Tap:(id)sender;
#end
///////// .m file
#synthesize mypDelegate;
.
.
.
.
- (void)processComplete
{
[[self mypDelegate] myProtocolMethodOne];
}
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