In my Application,
There are two different views ItemList And ItemSearch.
In ItemList file I have one NsMutableArray with name tblItem. I want pass data in tblitem from the Itemsearch page.
How can I do this?
You can make use of properties as follows:
1.Create a property in ItemList.h of tblItem as,
#property(nonatomic, retain) NSMutableArray *tblItem;
then synthesize it in ItemList.m,
#synthesize tblItem;
When you are navigating from ItemSearch to ItemList ie when you are initializing ItemList just provide tblItem the required values as,
ItemListObj.tblItem = theSearchedArray;
Declare an NSMutableArray as property in the SecondViewController and assign the array at the time you are pushing or presenting the SecondViewController from the FirstViewController.
#interface SecondViewController : UIViewController
{
NSMutableArray *aryFromFirstViewController;
}
#property (nonatomic,retain) NSMutableArray *aryFromFirstViewController;
#end
At the implementation, synthesize the property
#implementation SecondViewController
#synthesize aryFromFirstViewController;
#end
At the header of the FirstViewController import the SecondViewController
#import "SecondViewController.h"
At implementation of the FirstViewController, add the code like below in where you wrote the code to present or push the SecondViewController
#implementation FirstViewController
- (void) functionForPushingTheSecondViewController
{
SecondViewController *objSecondViewController = [[SecondViewController alloc] initWithNIBName: #"SecondViewController" bundle: nil];
objSecondViewController.aryFromFirstViewController = self.myAryToPass;
[self.navigationController pushViewController:objSecondViewController animated: YES];
[objSecondViewController release];
}
#end
Please don't forget to release the aryFromFirstViewController at dealloc method of SecondViewController, otherwise it will leak because we retained it. I'l feel good if i come to know that this helped you in someways. Enjoy.
It depends on your need. You can use Singleton class for sharing of your variables between different classes. Define all variable which you wants share in your DataClass.
in .h file (where RootViewController is my DataClass, replace name with your new class)
+(RootViewController*)sharedFirstViewController;
in .m file
//make the class singleton:-
+(RootViewController*)sharedFirstViewController
{
#synchronized([RootViewController class])
{
if (!_sharedFirstViewController)
[[self alloc] init];
return _sharedFirstViewController;
}
return nil;
}
+(id)alloc
{
#synchronized([RootViewController class])
{
NSAssert(_sharedFirstViewController == nil,
#"Attempted to allocate a second instance of a singleton.");
_sharedFirstViewController = [super alloc];
return _sharedFirstViewController;
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
// initialize stuff here
}
return self;
}
after that you can use your variable in any other class like this
[RootViewController sharedFirstViewController].variable
Hope it's help you:)
Related
I'm new to iOS development and I want to pass an NSMutableArray from one viewcontroller to another but always gives me null values
FirstViewController.h
#interface FirstViewController : UIViewController
#property (nonatomic, retain) NSMutableArray *colorArray;
-(IBAction)btn:(id)sender;
FirstViewController.m
#implementation FirstViewController
-(IBAction)btn:(id)sender
{
SecondViewController* secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondViewController.animalArray = self.colorArray;
NSLog(#"%#",secondViewController.animalArray); // here its not null
[self.navigationController pushViewController:secondViewController animated:YES];
}
SecondViewController.h
#interface SecondViewController : UIViewController
#property (nonatomic, retain) NSMutableArray *animalArray;
SecondViewController.m
I only used NSLog(#"animalArray:%#",self.animalArray); in viewDidLoad to check the values but gives me null
is there anything I'm missing?
Edit :
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"indidLoad%#",self.animalArray);
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(#"inwillAppear%#",self.animalArray);
}
Replace with following method
-(IBAction)btn:(id)sender{
SecondViewController* secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondViewController.animalArray=[[NSMutableArray alloc]initWithArray:self.colorArray];
[self.navigationController pushViewController:secondViewController animated:YES];
}
:) +1
If you call your NSLog from (void)viewWillAppear:(BOOL) animated, you should see something.
In your code example the viewDidLoad method is called straight after initWithNibName :
[[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
and before you have a chance to set your property.
**FirstViewController.h**
#interface FirstViewController : UIViewController
{
NSMutableArray *SongArray;
}
#property(nonatomic,retain)NSMutableArray *SongArray;
**FirstViewController.m**
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondView.SongArray = self.SongArray;
[self.navigationController secondView animated:YES];
**SecondViewController.h**
#interface SecondViewController : UIViewController
{
NSMutableArray *SongArray;
}
#property(nonatomic,retain)NSMutableArray *SongArray;
Do it like this your values arent being retained. Please also check Pass NSMutableArray to one view controller to another
Check the value in viewWillAppear instead of viewDidLoad.
It should work
-(IBAction)btn:(id)sender
{
SecondViewController* secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
NSLog(#"%#",secondViewController.animalArray); // here its not null
[self.navigationController pushViewController:secondViewController animated:YES];
secondViewController.animalArray = self.colorArray;
}
Sometimes if you pass value before pushing the the view it will give null value in second view
Better way is to create your NSMutableArray in Appdelegate file like below...
#property (nonatomic, retain) NSMutableArray *animalArray;//define this in Appdelegate.h file
synthesize it in Appdelegate.m file like
#synthesize animalArray;
Create Appdelegate object in prefix.pch file like below.
#define AppDel ((AppDelegate *)[UIApplication sharedApplication].delegate)
and import your Appdelegate file in prefix.pch like below..
#import "AppDelegate.h"
now where you want to use that array...just write like below..
AppDel.animalArray=//you can do whatever you want with array....
By doing this no need to pass array to other view controller, you can use that global array in whole project ,you can insert object in that array in any class and can access in any class.
Let me know it is working or not!!!
Happy coding!!!!
Here is my situation. I have ViewController class A with a button that goes to TableViewController class B by doing the following.
- (void) goToClassB
{
ViewControllerB *viewController =
[[ViewControllerB alloc] initWithStyle:UITableViewStylePlain];
// Present view controller modally.
if ([self
respondsToSelector:#selector(presentViewController:animated:completion:)]) {
[self presentViewController:viewController animated:YES completion:nil];
} else {
[self presentModalViewController:viewController animated:YES];
}
}
I want to be able to have an array that can be accessed and edited by both class A and class B. How can I achieve this?
Create a Array variable in Class B like:
#interface classB:NSObject
{
NSMutableArray *arrayFromA;
}
#property (nonatomic, assign) NSMutableArray *arrayFromA;
Synthesize the variable.
And in this method pass the array like:
- (void) goToClassB
{
ViewControllerB *viewController = [[ViewControllerB alloc] initWithStyle:UITableViewStylePlain];
[viewController setArrayFromA:yourArray];
// Present view controller modally.
if ([self
respondsToSelector:#selector(presentViewController:animated:completion:)])
{
[self presentViewController:viewController animated:YES completion:nil];
}
else
{
[self presentModalViewController:viewController animated:YES];
}
}
Create a NSMutableArray in ViewControllerA and pass it to ViewControllerB after your allocation.
This can be achieve Creating NSMutableArray And And Make it in Property assign in one of the class
#property(nonatomic,assign) NSMutableArray *array;
I mention that you want edit by both so.You can use application delegation for sharing app level variable. Check this link.
Some code is here. In your app delegate class.
#interface YourDelegateClass:UIResponder
{
NSMutableArray *array;
}
#property (nonatomic, assign) NSMutableArray *array;
You can access that array from everywhere of your app class with this code
YourDelegateClass * delegate =[[UIApplication shareApplication]delegate];
yourclassa.array = delegate.array;
or yourclassb.array = delegate.array;
Note: your must alloc *delegate.array* on your prefer at class or your delegate.
Create NSMutable array in view1 set property
#property(nonatomic,assign) NSMutableArray *array;
Create same array in viewB and set property and
#property (nonatomic, assign) NSMutableArray *arrayB;
#Synthesize that
Now at the time call viewB set value of array of viewA to viewB like this
ViewControllerB *viewController = [[ViewControllerB alloc] initWithStyle:UITableViewStylePlain];
[viewController arrayB:array];
The simplest way would, just as others point out, be simply passing the array to B by setting a property, but one other option would be to let B have a weak back reference to A. Thus you're always using the same array. This could be useful if A and B are changing the array at the same time.
#interface ViewControllerA : UIViewController
#property (nonatomic, strong) NSArray *array;
#end
#interface ViewControllerB : UIViewController
#property (nonatomic, weak) ViewControllerA *viewControllerA;
#end
/* When you're creating the ViewControllerB, do this: */
...
viewController.viewControllerA = self;
...
/* Use the array (From ViewControllerB) */
- (void)doSomethingWithTheArray
{
self.viewControllerA.array = ...
}
I have a view with a view controller and when I show this view on screen, I want to be able to pass variables to it from the calling class, so that I can set the values of labels etc.
First, I just tried creating a property for one of the labels, and calling that from the calling class. For example:
SetTeamsViewController *vc = [[SetTeamsViewController alloc] init];
vc.myLabel.text = self.teamCount;
[self presentModalViewController:vc animated:YES];
[vc release];
However, this didn't work. So I tried creating a convenience initializer.
SetTeamsViewController *vc = [[SetTeamsViewController alloc] initWithTeamCount:self.teamCount];
And then in the SetTeamsViewController I had
- (id)initWithTeamCount:(int)teamCount {
self = [super initWithNibName:nil bundle:nil];
if (self) {
// Custom initialization
self.teamCountLabel.text = [NSString stringWithFormat:#"%d",teamCount];
}
return self;
}
However, this didn't work either. It's just loading whatever value I've given the label in the nib file. I've littered the code with NSLog()s and it is passing the correct variable values around, it's just not setting the label.
Any help would be greatly appreciated.
EDIT: I've just tried setting an instance variable in my designated initializer, and then setting the label in viewDidLoad and that works! Is this the best way to do this?
Also, when dismissing this modal view controller, I update the text of a button in the view of the calling ViewController too. However, if I press this button again (to show the modal view again) whilst the other view is animating on screen, the button temporarily has it's original value again (from the nib). Does anyone know why this is?
When a view controller is being initialized, inside the initWithNibName method, the views that reside in the view controller aren't yet initialized and you can't set their properties yet. Do whatever you need that is view based in the "viewDidLoad" method.
I am not a pro but this may help you.
In the header view1.h, declare the desired property:
// view1.h
#interface view1 : UIViewController {
NSString *passingVariable;
}
#property (nonatomic, strong) NSString *passingVariable;
#end
and then in the implementation of view1, synthesize the variable:
// view1.m
#implementation view1
#synthesize passingVariable;
// the rest of the implementation
#end
and, finally in the implementation of the other view controller, view2:
// view2.m
#import "view1.h"
#implementation view2
-(IBAction)changeview
{
view1 *myview = [[view1 alloc] init];
myview.passingVariable = #"Hello Variable";
[self.navigationController pushViewController:myview animated:YES];
}
#end
here i am trying to move from view2 to view 1 and also initializing the passingVariable ivar of view1. hope this will help you.
Here i'm passing the ViewController's label text to SecondViewController's Label Text
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
// please make your control on XIB set these IBOutlet's
//I'm not showing how to connect these with XIB
IBOutlet UILabel *lblView;
IBOutlet UIButton *buttonGo;
}
//this is method which will push the view
-(IBAction)buttonGoClickAction:(id)sender;
ViewController.m
-(IBAction)buttonGoClickAction:(id)sender
{
SecondViewController *secondViewObject = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
//before pushing give the text
secondViewObject.string = lblView.text;
[self.navigationController pushViewController:secondViewObject animated:YES];
}
SecondViewController.h
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController
{
IBOutlet UILabel *labelView;
NSString *string;
}
//set the string property
#property(nonatomic, retain) NSString *string;
#end
SecondViewController.m
#import "SecondViewController.h"
#implementation SecondViewController
//synthesize string here
#synthesize string;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//Here you will get the string
labelView.text = string;
}
Firstly you check that have you attach this label IBOutlet in xib or not if you made it via Interface Builder....
use it like this....
SetTeamsViewController *vc = [[SetTeamsViewController alloc] initWithTeamCount:teamCount];
Take a string variable in .h file and set that string here .. NSSting *str in .h
- (id)initWithTeamCount:(int)teamCount {
self = [super init];
if (self) {
// Custom initialization
str = [NSString stringWithFormat:#"%d",teamCount];
}
return self;
}
and set your label in viewDidLoad: or in viewWillApear:
self.teamCountLabel.text = str;
May this will help you
As said by stavash, control in the xib are created in the view did load. To be more precise, they are created with that line :
[super viewDidLoad];
So, mylabel doesn't exist before that time (it is nil).
The easiest way is to do that :
SetTeamsViewController *vc = [[SetTeamsViewController alloc] init];
[self presentModalViewController:vc animated:YES];
vc.myLabel.text = self.teamCount;
[vc release];
The longer but more correct path is to have a member NSString* in SetTeamsViewController class, to set it to teamCount before showing the window, and in the view did load to put that membre value in your label.
Cdt
It depends on your need. You can use Singleton class for sharing of your variables between different classes. Define all variable which you wants share in your DataClass.
in .h file (where RootViewController is my DataClass, replace name with your new class)
+(RootViewController*)sharedFirstViewController;
in .m file
//make the class singleton:-
+(RootViewController*)sharedFirstViewController
{
#synchronized([RootViewController class])
{
if (!_sharedFirstViewController)
[[self alloc] init];
return _sharedFirstViewController;
}
return nil;
}
+(id)alloc
{
#synchronized([RootViewController class])
{
NSAssert(_sharedFirstViewController == nil,
#"Attempted to allocate a second instance of a singleton.");
_sharedFirstViewController = [super alloc];
return _sharedFirstViewController;
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
// initialize stuff here
}
return self;
}
after that you can use your variable in any other class like this
[RootViewController sharedFirstViewController].variable
Hope it's help you:)
With Storyboards the the right way is to pass the indexPath as sender argument in performSegueWithIdentifier
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"segueIdentifier" sender:indexPath];
}
and to set a property in the destination controller:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString: #"segueIdentifier"]) {
NSIndexPath *indexPath = sender;
DetailViewController *dest = [segue destinationViewController];
dest.usersArray = [self.usersArray objectAtIndex:indexPath.row];
}
}
What I have done whenever I needed another class to have the variables from the previous class I either set up a global class that will store the values incase I need them in more locations or in the interface you can set #public variables. These variables can be set using the controller that you created for the next view as such.
controller->pub_var1 = val1;
controller->pub_var2 = val2;
This will be done before you pass the view to the root controller or just before you call the next view. You will need to #import "class.h" so that you can access those public variables.
I can show code if this is not clear
FirstViewController.h:
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController
{
NSArray *listData;
}
-(IBAction) GoToInsert: (id) sender;
#property (nonatomic, retain) NSArray *listData;
#end
FirstViewController.m:
-(IBAction) upisiRezultat:(id)sender
{
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName: nil bundle: nil];
[self presentModalViewController: secondView animated: NO];
[secondView release];
}
- (void)viewDidLoad
{NSArray *array = [[NSArray alloc] initWithObjects:#"236", #"46",
#"147", #"8", #"56", #"69", #"114", #"2",
#"96", #"518", #"2", #"54", #"236", nil];
self.listData = array;
[array release];
[super viewDidLoad];
}
SecondViewontroller.h
#interface SecondViewController : UIViewController {
}
-(IBAction) insert;
#end
SecondViewontroller.m
-(IBAction) insert
{
/* Here should be the code to insert some number in listData from FirstViewController */
}
So when the app loads it loads FirstViewController.xib and shows the listData array on screen, when I click button "Go to Insert" another view is loaded (SecondViewController.xib) with button "Insert" which should add some number into the array and display the new array on the first view.
How to do that?
You can access the parent view controller with self.parentViewController. Therefore something along these lines (meaning I haven't tested this -- you should) should work:
FirstViewController *firstViewController = self.parentViewController;
NSMutableArray *newArray = [[NSMutableArray alloc] initWithArray:firstViewControl.listData];
[newArray addObject:#"42"];
[firstViewController setListData:[NSArray arrayWithArray:newArray]];
[newArray release];
However, since you want to add objects to listArray, it would be more natural to use an NSMutableArray instead. Also, you are currently adding NSStrings to the array, when it looks more like you want to have NSNumber objects.
Alternately, and maybe easier, you could have the variables in your main AppDelegate.
Put:
int myNumber;
in the projectname_AppDelegate.h file
Then in each of your view controllers, you can import your AppDelegate.h file and then do something like:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
and then read or change:
appDelegate.myNumber
===
This is not something you should be doing all the time (you don't want your appDelegate to be a giant data repository) but it could give you a quick fix when needed...
I do not know if you have imported the SecondViewController.h , and I think I have an idea an what you are trying to do.
In my application i have some view controllers and one objective c class ,how can i access the UI elemets of one view controller to change their values in objective class .
To explain further , i have a UILable *lab in the firstviewcontroller and just imported
#import "firstViewController.h"
in my customclass.m file and i am trying to do like this in one method of objective c class
firstViewController.lab.text=#"example";
( i know its not correct method but i am trying to explain what i am doing )
can any one please tell me how can i do that ?
First thing you need to do is grab a reference to the view controller you wish to operate on. One way to do this and have it available to other classes is to store a reference to it in a singleton object that you instantiate in your customclass.m. Specifically this is how this method works:
Define Singleton Object:
#import <Foundation/Foundation.h>
#interface MySingleton : NSObject {
MyViewController *myViewController;
}
#propery (nonatomic. retain) MyViewController *myViewController;
+(MySingleton*)sharedMySingleton;
#implementation MySingleton
#synthesize myViewController;
static MySingleton* _sharedMySingleton = nil;
+(MySingleton*)sharedMySingleton
{
#synchronized([MySingleton class])
{
if (!_sharedMySingleton)
[[self alloc] init];
return _sharedMySingleton;
}
return nil;
}
+(id)alloc
{
#synchronized([MySingleton class])
{
NSAssert(_sharedMySingleton == nil, #"Attempted to allocate a second instance of a singleton.");
_sharedMySingleton = [super alloc];
return _sharedMySingleton;
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
// initialize stuff here
}
return self;
}
#end
Whereever you instantiate your myViewController you do this:
#import "MySingleton.h"
MySingleton *sinlgeton = [MySingleton sharedMySingleton];
singleton.myViewController = myViewController;
Now in your CustomClass.m you do this:
#import "MySingleton.h"
MySingleton *sinlgeton = [MySingleton sharedMySingleton];
singleton.myViewController.lab.text = #"example"
As I said this is ONE WAY to do this. However, you most probably DO NOT want to access and change view controller properties in a custom class so you should really rethink why you are doing this at all.
As with most programming tasks there are several solutions and it depends on the situation.
You can have FirstViewController own the instance of the MyCustomClass and then pass itself.
#interface FirstViewController : UIViewController {
MyCustomClass *customClass_;
}
#end
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
customClass_ = [[MyCustomClass alloc] init]
customClass_.firstViewController = self;
}
#end
#interface MyCustomClass : NSObject {
FirstViewController *firstViewController;
}
#property (nonatomic, assign) FirstViewController *firstViewController;
#end
This way MyCustomClass can access the properties of FirstViewController. If you don't want to give MyCustomClass access to all of FirstViewController you can use pass along the properties that MyCustomClass should know about.
#interface FirstViewController : UIViewController {
MyCustomClass *customClass_;
UILabel *lab;
}
#property (nonatomic, retain) IBOutlet UILabel *lab;
#end
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
customClass_ = [[MyCustomClass alloc] init]
customClass_.lab = self.lab;
}
#end
#interface MyCustomClass : NSObject {
UILabel *lab;
}
#property (nonatomic, retain) IBOutlet UILabel *lab;
#end
It could very well be the case that it doesn't make sense for FirstViewController to be the owner of MyCustomClass. Perhaps it is the AppDelegate or some parent controller that have access to both instances.
#interface RandomParentClass : NSObject {
FirstViewController *firstViewController;
MyCustomClass *customClass:
}
#end
#implementation RandomParentClass
- (void)setUpController {
firstViewController = [[FirstViewController alloc] init];
customClass = [[MyCustomClass alloc] init];
customClass.lab = firstViewController.lab;
// or
customClass.firstViewController = firstViewController;
}
#end