I know this question as been asked over and over but it's still quite obscure to me, so I guess making an example with my code instead will probably be easier .
I know that you can use :
A global variable, ( not good practice ).
Use a delegate
Use a singleton
Say I've got this piece of code here in my first view controller header :
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController {
IBOutlet UITextField *Te;
NSInteger evTe;
}
#property (nonatomic, retain) UITextField *Te;
#property (nonatomic) NSInteger evTe;
- (IBAction) makeKeyboardGoAway;
#end
and then this in my implementation file
#import "FirstViewController.h"
#implementation FirstViewController
#synthesize Te;
- (IBAction) makeKeyboardGoAway;
{
[Te resignFirstResponder];
evTe = [Te.text intValue];
}
How would I call evTe in my SecondViewController ? ( maybe using a delegate ?) .
This is what I've got in the second view Controller, header :
#interface SecondViewController : UIViewController {
NSInteger evTe;
}
#property (nonatomic) NSInteger evTe;
and implementation :
- (IBAction) makeKeyboardGoAway;
{
FirstViewController *first = [[FirstViewController alloc] init];
first.evTe = self.evTe;
NSLog(#"second value is %i",evTe);
}
Thanks a lot !
Edit for Tob
FirstViewController.m
- (IBAction) makeKeyboardGoAway;
{
evTe = [Te.text intValue];
NSLog(#"The value of integer num is %i", evTe);
NSDictionary *changedValues = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:evTe] forKey:#"evTe"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"evTeChanged" object:self userInfo:changedValues];
}
SecondViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(methodToCall:) name:#"evTeChanged" object:nil];
}
- (void)methodToCall:(NSNotification *)aNotification{
NSDictionary *changedValues = [[aNotification userInfo] objectForKey:#"evTe"];
NSString *dictionaryString = [changedValues description];
NSLog(#"Notification returning %d",dictionaryString);
}
Unfortunately I'm not getting any log from the SecondView ..
By creating a #property called evTe or whatever in both view controllers.
If the FirstViewController is responsible for creating the SecondViewController you could store the value of evTe in a property in FirstViewController and then after you have created the SecondViewController you set the evTe property there as well.
- (IBAction) makeKeyboardGoAway;
{
[Te resignFirstResponder];
self.evTe = [Te.text integerValue];
}
// other method where SecondViewController is created
SecondViewController* second = [[SecondViewController alloc] init];
second.evTe = self.evTe;
// do what ever
--Edit--
#interface FirstViewController : UIViewController {
IBOutlet UITextField *Te;
NSInteger evTe;
}
#property (nonatomic, retain) UITextField *Te;
#property (nonatomic) NSInteger evTe;
Have a look at NSNotification. You should send a notification that the particular value has changed and register for that notification in the second view controller.
- (IBAction) makeKeyboardGoAway;
{
[Te resignFirstResponder];
evTe = [Te.text intValue];
NSDictionary *changedValues = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:evTe] forKey:#"evTe"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"evTeChanged" object:self userInfo:changedValues];
}
And in the viewDidLoad method of the other controller do:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(methodToCall:) name:#"evTeChanged" object:nil];
Now every time the first controller calls makeKeyboardGoAway the method - (void)methodToCall:(NSNotification *)aNotification will be called.
Implement this method and ask the aNotification for its userInfo which is the NSDictionary you created in the first controller before posting the notification. Get the evTe value out of it and do whatever you want to do with that value.
Related
I'm working on an iPad App and i'm having issue with delegate... the protocol method does not get invoked. i'm not sure what i'm missing, here is my code.
#protocol pickerLabelProtocol <NSObject>
- (void)selectedPickerData:(UILabel *)sender;
#end
#interface showPickerVC : UIViewController
#property (nonatomic, strong) id <pickerLabelProtocol> delegate;
#end
#implementation showPickerVC
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//i used breakpoint, the 'delegate' is always nil for some reason?
[self.delegate selectedPickerData:self.mainLabel];
}
----------------------
#interface someViewController : UIViewController <pickerLabelProtocol>
#property (nonatomic, strong) showPickerVC *showPicker;
#end
#implementation someViewController
- (void)selectedPickerData:(UILabel *)sender
{
//protocol method
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.showPicker = [[showPickerVC alloc]init];
self.showPicker.delegate = self;
}
I can not got any mistake From your code but i suggest you that Be clear about when you create object of showPickerVC add it's delegate self
Such Like ,
showPickerVC *obj = [[showPickerVC alloc] init];
obj.delegate = self; /// YOur protocol delegate
.
.
[self presentModalViewController:obj animated:YES];
And Also add code as following
#implementation showPickerVC
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if([self.delegate respondsToSelector:#selector(selectedPickerData:)])
{
[self.delegate selectedPickerData:self.mainLabel];
}
}
For More information about How to create/use of Protocol.
I have a view controller and a class (I am using storyboards). How can I change the text of a UILabel (in the view controller) from the class? I have tried this, but to no avail:
ViewController *mainView = [[ViewController alloc] init];
[mainView view];
[mainView.progressBar setProgress:integer animated:YES];
NSLog(#"Updated Progress Bar");
NSString *progressLabelText = [NSString stringWithFormat:#"%# out of %i followers", userString, [self.followers count]];
[mainView.progressLabel setText:progressLabelText];
NSLog(#"Updated Progress Label Text: %#", progressLabelText);
The text does not change using this code. What should I be doing instead?
Edit: The progressbar and label in the ViewController's .h file look like this:
#property (nonatomic, strong) IBOutlet UIProgressView *progressBar;
#property (nonatomic, strong) IBOutlet UILabel *progressLabel;
And they are fully linked up in Interface Builder.
Use delegate for messaging between classes or viewcontrollers.
Refer The Basics of Protocols and Delegates link.
Try to use Notification for updating the Lable text.
in your viewController write this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateLabel) name:#"lblUpdate" object:nil];
and selector is :
-(void)updateLabel
{
self.lblObject.text = #"Your updated text"
}
and now in your Class call this using Post notification:
[[NSNotificationCenter defaultCenter] postNotificationName:#"lblUpdate" object:nil];
remember use same notification name "lblUpdate"
just property synthesize the string and then set that string in viewWillAppear: method of ViewController.m class
just take NSString variable in ViewController.h file like bellow..
#property (nonatomic, retain) NSString *progressText;
and synthesize this in ViewController.m file like bellow..
#synthesize progressText;
after that in viewDidLoad: method just set text at starting to the progressLableText like bellow...
- (void)viewDidLoad
{
progressText = #"Your Text";
[progressLabel setText:progressText];
}
and also in viewWillAppear: set the text like above...
- (void)viewWillAppear:(BOOL)animated
{
[progressLabel setText:progressText];
}
and in your code just change something like bellow..
ViewController *mainView = [[ViewController alloc] init];
[mainView view];
[mainView.progressBar setProgress:integer animated:YES];
NSLog(#"Updated Progress Bar");
NSString *progressLabelText = [NSString stringWithFormat:#"%# out of %i followers", userString, [self.followers count]];
mainView.progressText = progressLabelText;
[mainView.progressText retain];
NSLog(#"Updated Progress Label Text: %#", progressLabelText);
i hope this helpful to you...
But use a delegate to do the callbacks.
In your spamchecker.h add:
#protocol SpamCheckerDelegate <NSObject>
-(void)updateText:(NSString*)newText;
#end
#property (nonatomic, weak) id <SpamCheckerDelegate> delegate;
In your spamchecker.m where you need it add:
[self.delegate updateText:#"newText"];
Then in your mainView.h add:
#interface MainView : UIViewController <SpamCheckerDelegate>
In your mainview.m add:
spamchecker.delegate = self;
And implement the method like:
-(void)updateText:(NSString*)newText
{
[self.progressLabel setText:progressLabelText];
}
I have to pass a UITextField value from one view to other views(2nd,3rd...views).Actually in my 3rd ViewController I have a scrollView and I have to display value on it .But UITextField value is not getting passed.It is returning null.Couldn't get what might be wrong?
THis is the code I am working with:
In ViewController1.m:
-(IBAction)butonclick:(id)sender{
ViewController2 *view2=[ViewController2 alloc];
view2.id=name.text;
ViewController3 *view3=[ViewController3 alloc];
view3.id=name.text;
[view2 release];
[view3 release];
}
IN ViewConroller2.h :
#interface ViewController2 : UIViewController {
NSString *id;
UIlabel *displayId;
}
In ViewController2.m :
- (void)viewDidLoad
{
self.displayId.text=self.id;
}
In ViewController3.h:
#interface ViewController2 : UIViewController {
NSString *id;
UIlabel *dispId;
}
In ViewController3.m :
- (void)viewDidLoad
{
self.dispId.text=self.id;
}
But here the id value is not passed to ViewController3.It is returning null ..Where I m going wrong?
You are passing the values without initializing.
ViewController2 *view2=[[ViewController2 alloc]init];
view2.id=name.text;
ViewController3 *view3=[[ViewController3 alloc]init];
view3.id=name.text;
If you want to use object globally within your app, you can declare it in the appDelegate.
In AppDelegate.h
#interface AppDelegate : NSObject <NSApplicationDelegate>
{
NSString *idGlobal;
}
#property (nonatomic, retain) NSString *idGlobal;
In AppDelegate.m
#synthesize idGlobal;
In ViewController1.m:
-(IBAction)butonclick:(id)sender{
appDelegate.idGlobal=name.text;
}
In ViewController2.m: and
In ViewController3.m:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
id=appDelegate.idGlobal;
Declare the string globally in the AppDelegate.h this will help in keeping the value of the string constant throughout the files. Also wherever you want to add the string or change its value or assign it import the AppDelegate.h .
Also check these links :-
passing NSString from one class to the other
Pass NSString from one class to another
I am just correcting the code you have written meanwhile the suggestions given above for using AppDelegate property is a good one.
The main problem with your code is that you are just declaring NSString object instead of making it a property. Check this:
-(IBAction)butonclick:(id)sender{
ViewController2 *view2=[ViewController2 alloc]init];
view2.str=name.text;
ViewController3 *view3=[ViewController3 alloc]init;
view3.str=name.text;
[view2 release];
[view3 release];
}
IN ViewConroller2.h :
#interface ViewController2 : UIViewController {
NSString *str;
UIlabel *displayId;
}
#property(nonatomic, retain) NSString* str; //Synthesize it in .m file
In ViewController2.m :
- (void)viewDidLoad
{
self.displayId.text=self.str;
}
In ViewController3.h:
#interface ViewController2 : UIViewController {
NSString *str;
UIlabel *dispId;
}
#property(nonatomic, retain) NSString* str; //Synthesize it in .m file
In ViewController3.m :
- (void)viewDidLoad
{
self.dispId.text=self.str;
}
I am not aware with your scenario but the most effective way of implementing such situations is using Delegates. Make a delegate of the class where your string is being set (ViewController1) and set delegate accordingly in your other view controllers.
In this code I'm attempting to pass an array from one tab view to another using protocols. The method itself is a simple get method with one line returning an a mutableArray. Within it's own class it works, within this class it is not even called.
- (void)viewDidLoad
{
[super viewDidLoad];
myLocationEntityArray = [[NSMutableArray alloc] initWithArray:[[self delegate] getMyLocationEntityArray]];
}
The header file for the class receiving the data:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#protocol CoreDataDelegate;
#interface ListTableViewController : UITableViewController
{
NSManagedObjectContext *managedObjectContext;
NSMutableArray *myLocationEntityArray;
id <CoreDataDelegate> delegate;
}
- (NSMutableArray *)fetchCoreData;
#property(nonatomic, retain) NSManagedObjectContext *managedObjectContext;
#property(nonatomic, assign) id <CoreDataDelegate> delegate;
#property(nonatomic, retain) NSMutableArray *myLocationEntityArray;
#end
#protocol CoreDataDelegate
//- (NSMutableArray *) fetchCoreData;
- (NSMutableArray *) getMyLocationEntityArray;
#end
The top of the header file sending the data:
#interface MapViewController : UIViewController <CLLocationManagerDelegate, CoreDataDelegate>
First you should change your procotol like this :
#protocol CoreDataDelegate
//- (NSMutableArray *) fetchCoreData;
- (void) getMyLocationEntityArray:(NSMutableArray *)entityArray;
#end
You set your MapViewController to responds to your protocol CoreDateDelegate. So, I suppose you alloc your ListTableViewController inside the MapViewController. If that is the case, you need to do this :
// MapViewController.m
...
ListTableViewController *listVC = [[ListTableViewController alloc] init];
listVC.delegate = self;
// display your listVC
...
// Somewhere in your code of MapViewController.m
- (void) getMyLocationEntityArray:(NSMutableArray *)entityArray {
// do something with entityArray
}
EDIT
Following your comments, here is a simpler way to do what you want. NSNotification. It does not require protocol, and is easier to implement.
// In ListTableViewController.m
// In Init or viewDidLoad function
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(getEntity:)
name:#"GetEntity"
object:nil];
- (void)getEntity:(NSNotification *)notif {
NSArray *entityArray = (NSArray *)[notif object];
// do something with entityArray
}
// In dealloc or viewDidUnLoad function
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"GetEntity"
object:nil];
// In MapViewController.m
// theEntityArray to be defined
[[NSNotificationCenter defaultCenter] postNotificationName:#"GetEntity"
object:theEntityArray
userInfo:nil];
In few words, when you will post the GetEntity notification in MapViewController, it will call undirectly the -(void)getEntity: function of ListTableViewController
I have 4 classes i.e views in my application. Class A, having variable a and b.
After clicking on button which is on view A of class A it leads to class B, which is table view controller. Then class B leads to class C. then class C leads to class D.
Now i want to access values of a and b of class A into class D. I tried it with NSNotification but not succeeded.
Please suggest.
I tried with NSNotification:
i tried with NSNotification like Class A---
-(IBAction) selectButton:(id) sender{
NSString * a = [NSString stringWithFormat:#"Manjinder singh"];
NSDictionary * dict = [NSDictionary dictionaryWithObject:a forKey:#"1"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"sendMessage" object:self userInfo:dict];
}
Then Class D----
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(sendMessage:) name:#"sendMessage" object:nil];
}
return self;
}
-(void)sendMessage:(NSNotification *)notification{
A *dil=[[A alloc] init];
nslog(#"dil.a");
NSLog(#"USERINFO:MyUserInfo (its a dictionary):%#",[[notification userInfo] valueForKey:#"1"]);
}
This is the rendom try but basically i want to show variable a and b of class A into class D.
Update:------------
MyCoolViewController.h// a class where data send from
#protocol MyCoolViewDelegate;
#interface MyCoolViewController : UIViewController {
id <MyCoolViewDelegate> delegate;//
}
#property (nonatomic, assign) id delegate;//
#end
#protocol MyCoolViewDelegate <NSObject>//
-(void)sendAStringToAnotherView:(NSString*)string;
#end
MyCoolViewController.m
-(void)viewDidLoad{
[delegate sendAStringToAnotherView:#"this is a string"];
}
firstViewController.m //a class where data sent
-(void)viewDidLoad{
MyCoolViewController *myViewControllerPointer=[[MyCoolViewController alloc] init];
myViewControllerPointer.delegate = self;//
}
-(void)sendAStringToAnotherView:(NSString*)string
{
//displays the string as console output
NSLog(#"plzzzzzz show data",string);
}
value of string is not passed to this class because it is not showing in NSLog output.
UPDATED 2---
MyCoolViewController.m
#import “MyCoolViewController.h”
#import "firstViewController.h"
#implementation MyCoolViewController
#synthesize label1,sttr;
#synthesize delegate;//
-(IBAction) selectButton:(id) sender{
if (curri==nil) {
curri=[[CurrancyViewController alloc] initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:curri animated:YES];
}
curri=nil;
//CHECK ThIS [curri release];
}
- (void)viewDidLoad
{
[delegate sendAStringToAnotherView:#"this is a string"];
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"background1.png"]];
[super viewDidLoad];
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
Can you give more context about what specifically you are trying to achieve? It sounds like you want to pass data between several UIViewControllers. Here is how to set up a delegate for one of your view controllers:
#import <UIKit/UIKit.h>
#protocol MyCoolViewControllerDelegate;
#interface MyCoolViewController : UIViewController {
id <MyCoolViewControllerDelegate> delegate;
}
#property (nonatomic, assign) id delegate;
#end
#protocol MyCoolViewControllerDelegate <NSObject>
-(void)sendAStringToAnotherView:(NSString*)string;
#end
Then you will should synthesize the delegate
#synthesize delegate;
and then when you want to pass data to, lets say a parent view, call this function:
[delegate sendAStringToAnotherView:#"this is a string"];
In the other view controller, wherever you instantiated the instance of this UIViewController, you need to set that self as the delegate;
myViewControllerPointer.delegate = self;
and then implement the delegate function in the parent view controller.
-(void)sendAStringToAnotherView:(NSString*)string
{
//displays the string as console output
NSLog(string);
}
The fact that you need communicate between views like this could possibly mean that there is a more efficient means of structuring your app. Can't say for sure without more info.
Try and use this template to add a delegate to your own app.
You could use delegation here
D would become the delegate of A, and when you click the button, A sends a message to D with the variables as arguments and D responds by performing a method.