Accessing NSMutableArray in an object from different object - iphone

How can I get access to a NSMutableArray that has been hydrated in different Class?
There is my sample code:
Class1.h : I have an iVar NSMutableArray *anArray;
And I #synthesize anArray; it in Class1.m
In the RootViewController I import the Class1.h and addd #Class "Class1";
The in the interface I add the Class1 *aClass1; in the RootViewController.m I #synthesize it and in the ViewWillAppear
aClass1 = [[Class1 alloc] init];
aClass1.anArray = [[NSMutableArray alloc] initWithObjects: #"string1",#"string2",nil];
NSLog(#"aClass1.anArray is Class1 %#",aClass1.anArray); // It works as I expected
Now in the new class I call it DetailsViewController
Same as the RootViewController.h I imported the .h and #class "Class1";.
Also in the DetailsViewController.m I have imported the "Class1.h"
So now in the DetailsViewController I try to do this in the viewWillAppear
NSLog(#"aClass1.anArray in DetailsViewController %#",aClass1.anArray); // PROBLEM: It comes back as null
I have added this sample project in this address: http://www.epicdesign.com.au/test2.zip

You just forgot to set the aClass1 ivar of the details view controller before you pushed it onto the navigation controller. Here is the code that should be in your didSelectRowAtIndexPath method:
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
// ...
// Pass the selected object to the new view controller.
detailViewController.aClass1 = aClass1; // this line was added
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
Once you add the line that I added above, your array will now show up correctly in the detail view controller.

You're accessing a property that you haven't declared yet in the Class1.h, so you must add there:
#property (nonatomic, copy) NSMutableArray *anArray;
Since it should work, I prefer not to pass any NSMutableArray as parameter. You should better declare a NSArray property in Class1.h to pass it to your methods and then mutableCopy it where you want to make modifications to the array (only inside the methods). And remember that mutableCopy and copy increase the retain count of your array, so you must release it when you are done.

Related

How to pass data between not neighbor view controllers in Storyboard

I've stuck in the problem.
I have a storyboard with several view controllers.
What I need to do is:
I need to pass an array from FirstViewController to SecondViewController (they are not neighbors and are not connected via segue) where PikerView will upload the array. After that the picked result should be passed to ThirdViewController.
I have tabbed applicateion where FirstViewController and SecondViewControllers are connected to Tab Bar View Controller and ThirdViewController is connected with SecondViewController via Push Segue.
See how I try to pass data form First to Second
CategoryExpencesViewController.h
#import <UIKit/UIKit.h>
#import "AddCategoryViewController.h"
#import "CategoryPickerViewController.h"
#interface CategoryExpencesViewController : UITableViewController <AddCategoryViewControllerDelegate>
#property(nonatomic, weak) IBOutlet UIBarButtonItem *editButton;
#property(nonatomic, strong) NSMutableArray *categories; //list of category items
#property(nonatomic, strong) NSMutableArray *listOfCategories; //list of category names
CategoryExpencesViewController.m
-(void)updateArray
{
CategoryPickerViewController *controller = [[CategoryPickerViewController alloc]init];
controller.categoryList = [[NSMutableArray alloc]init];
controller.categoryList = listOfCategories;
NSLog(#"%d", [listOfCategories count]);
NSLog(#"%d", [controller.categoryList count]);
}
I think you need this
Use your's Push Segue.
segue.sourceViewController (or self) will point at SecondViewController.
segue.sourceViewController.tabBarController will point at Tab Bar Controller.
From Tab Bar Controller you will find your's FirstViewController.
I suppose you would have solved it, but i post this just for the record:
Wrap the array into a class, and make it have a static construction method:
Wrapper.h:
#property (nonatomic, strong) NSMutableArray* array;
+(Wrapper*)createArray;
Wrapper.m:
+(Wrapper*)createArray{
static Wrapper* instance = nil;
if (instance == nil) {
instance = [[Wrapper alloc] init];
//Your initialization code for the array
}
return instance;
}
Then, in your FirstViewController:
-(void)updateArray{
CategoryPickerViewController *controller = [[CategoryPickerViewController alloc]init];
controller.categoryList = [[NSMutableArray alloc]init];
controller.categoryList = [[Wrapper createArray] array];
NSLog(#"%d", [listOfCategories count]);
NSLog(#"%d", [controller.categoryList count]);
}
As this is the first call to Wrapper, the array is generated.
Then in your SecondViewController, when you call:
secondView.categoryList = [[Wrapper createArray] array];
and you obtain the same array as in FirstViewcontroller.
have you thought of NSUserDefault try it and you can also create a instance global variable in AppDelegate class and access it by creating an instance of AppDelegate in any other ViewController but i think NSUserDefault is the best option from all.

How Can I Access my ViewController's Property Variables From Another Class?

Ok, this is really bugging me and I am sure the solution is simple... I am unable to set my ViewController's property variables from another class (SeverConnect.m), which I have declared and synthesized properly in my ViewController's .h/.m files:
ServerConnect.h:
#import <Foundation/Foundation.h>
#import "ViewController.h"
#import "Contact.h"
#class ViewController;
#interface ServerConnect : NSObject
{
Contact *newContact;
NSString *codeRawContent;
NSMutableArray *contactListCopy;
... //Other variables declared here, but not shown in order to save space
Inside ServerConnect.m:
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(#"parserDidFinish");
newContact = [[Contact alloc] initWithCodeInfo:(NSString *)codeInfo
contactName:(NSString *)completeName
contactImage:(UIImage *)profileImage
contactWebSite:(NSString *)codeRawContent];
[contactListCopy insertObject:newContact atIndex:0];
[ViewController setContactList:contactListCopy]; //Automatic Reference Counting Error Occurs Here: "No known class method for selector 'setContactList:'"
}
As I mentioned above, I have declared and synthesized the property variable, "contactList", in my ViewController's .h/.m files (with no errors):
#property (nonatomic, retain) NSMutableArray *contactList; //In ViewController's .h file
#synthesize contactList; //In ViewController's .m file
Can someone tell me what I am doing wrong? Thanks in advance for any help you can provide!
you are trying to access an instance property on a class:
[ViewController setContactList:contactListCopy];
you need to first create an instance of the ViewController class, and then set its property. Something like this:
ViewController *viewController = [[ViewController alloc] init];
[viewController setContactList:contactListCopy];
In this line of code:
[ViewController setContactList:contactListCopy];
you should be using a variable of type ViewController. The way you are using it, it should be a class method, not a property.
Write something like:
ViewController *viewController = [[ViewController alloc] init];
[viewController setContactList:contactListCopy];

How to pass variable from one controller to another in ios?

I have one controller with variable like
NSString *str;
In same controller i am assigning userId in string str.
I need above userId in another controller to show user data.
How should I get value of userId in another controller?
Below is my code:
MainViewController.h
#property (nonatomatic) NSString *str;
MainViewController.m
#synthesize str;
str = 1;
Now in FirstViewController.h
#property(nonatomatic, retain) MainViewController *mainCon;
FirstViewController.m
#synthesize mainCon;
NSLog(#"user id is %#", mainCon.str);
Here in log i am getting null value.
Your best bet is going to be in the [prepareForSegue] method
within that method I usually have something like
if ([segue.identifier isEqualToString#"segueName"]){
//I use this if statement to check which segue I am performing, if I have multiple
//segues from a single view controller
FirstVc *newViewController = segue.destinationViewController;
newViewController.str = self.str;
}
This will pass the string from your main VC to your new VC. This is all assuming that your transitions are laid out in Interface Builder or some way that gives you access to the segues and identifiers
Take a Property in MainVC and Pass value from FirstVC then It will work for you.
the following code must be in MainVC
#property (strong, nonatomic) NSString *str;
#synthesize str;
in FirstVC
MainVC * vc = [[MainVC alloc]init];
vc.str = #"test";
Step1:
You have to create a viewcontroller class as Constants
Step 2:
You can delete .m file in Constanst class
Step3:
You have to import the Constants.h in Projectname_Prefix.pch which will be xcode's in other resources folder. Now Constant class will act as global class.
Step4:
Now, you can declare variables in Constants.h. The variables those declared in Constants.h will act as global variable. you can access it anywhere.
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondViewController.str1 = str;
[self.navigationController pushViewController:secondViewController animated:YES];
It's a quicker and easy solution.

how can I display MSMutableArray data in UITableViewController?

I am getting data from NSTextField, and saving data in NSMutableArray. I want to show the same data in another class which in child of UITableViewController.
How can I show data of NSMutableArray to myTableView which is another class??
Help me out, please
Surely, I will appraise if I found proper way.
Your tableView is in a MyViewController class. You need to create a NSMutableArray *sourceArray attribute on that class, as well as the associated property, using for instance:
#property (nonatomic, retain) NSMutableArray *sourceArray;
Then when you instantiate this View Controller or whenever you make it appear, assign the results to sourceArray :
MyViewController *mvc = [[MyViewController alloc] initWith...];
mvc.sourceArray = theResult;
[self presentModalViewController:mvc animated:YES];
[mvc release];
Then use the sourceArray as the Table View datasource.
Make a property of NSMutableArray in app delegate class and assign the result of the source array to it as soon as you fetch any result, because you can access its instance all over your project.

iPhone - UINavigationController question

I want to display some data on table, let's call it "TabeView" app.
So I created a "navigation-based" application on XCode and it gives me 4 files in the "classes folder".
RootViewController.h
RootViewController.m
TableViewAppDelegate.h
TableViewAppDelegate.m
Now, I wanted to set up the data in TableViewAppDelegate using the "didFinishLaunchingWithOptions" method, which I did using an array.
Then, I need to "send" this array to the RootViewController. I have an array variable in RootViewController so I assume that I need to "set" the array variable in RootViewController from the TableViewAppDelegate. How can I do this?
The problem I am having is, that I don't know how to set the array variable in RootViewController from TableViewAppDelegate. I want to know if something like below is possible
....
[RootViewController setMyArray:myArray];
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
....
But I have no idea how to call "RootViewController".
Hopefully I made some sense. Thank you.
First, create a property in your RootViewController class for the array variable. So e.g. if your array variable is called myArray your code might look something like this:
In RootViewController.h:
#import <UIKit/UIKit.h>
#interface RootViewController : UITableViewController {
NSArray *myArray;
}
#property (nonatomic, retain) NSArray *myArray;
#end
and add the corresponding #synthesize line in RootViewController.m:
#import "RootViewController.h"
#implementation RootViewController
#synthesize myArray;
// methods here
#end
Now you can set the myArray member of a RootViewController object like this:
myRootViewController.myArray = [NSArray arrayWithObjects:#"foo", #"bar", nil];
Now, in your app delegate class, you can use the viewControllers property of self.navigationController to return the view controllers in the navigation stack. The root controller will always be at index 0. viewControllers will return an NSArray, whose elements are of type NSObject, so you need to cast to a RootViewController pointer too. Here it is in two lines, to make the cast explicit:
// get a pointer to the root view controller
id obj = [self.navigationController.viewControllers objectAtIndex:0];
// cast it to a RootViewController pointer
RootViewController* rvc = (RootViewController*)obj;
// Now you can set the array
rvc.myArray = someArray;
(In order to use the RootViewController class name in your app delegate class you'll need to import the relevant header file - put this at the top of TableViewAppDelegate.m:
#import "RootViewController.h"
And that's it!
p.s. Bear in mind that declaring your myArray property as type (nonatomic, retain) means that your RootViewController object will end up pointing to the same instance of NSArray that you pass to it. So, for example:
NSMutableArray *array = [NSMutableArray arrayWithObjects: #"foo", #"bar", nil];
myRootViewController.myArray = array;
[array removeAllObjects]; // myRootViewController.myArray is now empty!
You can use (nonatomic, copy) instead, in which case your RootViewController object will make a copy of the array you pass in and retain that instead. Changes to the array once you've assigned it to your RootViewController object won't affect the copy.
navigationController.myArray = myArray;
before
[window addSubview:navigationController.view];