Sharing NSMutableArray - iphone

Hey everbody, im trying to share a NSMutableArray to another xib. The cartList.codigo is a NSMutableArray from a shared class, according to James Brannan's tutorial (http://www.vimeo.com/12164589).
When i count it, it gives me 1. But when i load the another view, gives me 0.
Whats wrong?
View that adds:
self.produtoCodigo = [[NSMutableArray alloc]init];
[self.produtoCodigo addObject:#"aa"];
CartViewController *carrinho = [[CartViewController alloc] initWithNibName:#"CartViewController" bundle:[NSBundle mainBundle]];
CartList *lista = [[CartList alloc] init];
carrinho.cartList = lista;
carrinho.cartList.codigo = self.produtoCodigo;
NSLog(#"QTD %i", [carrinho.cartList.codigo count]);
View that wants to load the item added:
- (void) viewDidAppear:(BOOL)animated {
self.produtoCodigo = self.cartList.codigo;
NSLog(#"%i", [self.produtoCodigo count]);
[super viewDidLoad];
}
Im loading the CartList class in both.
Thanks!

My guess is that you are not retaining the array, but only assigning it.
Do you retain the array in the view, something like this -
#property (nonatomic, retain) NSMutableArray * produtoCodigo;
the "retain" gives your view controller an ownership on the array and you can use it.
Since I don't have your code that is the best I can do to help.
shani
UPDATE -
Ok. you do retain it but now i see that the "produtoCodigo" array is retained but you dont pass the array in the view controller.
is seems that you can do 2 things:
in your view controller pass the viewController "produtoCodigo" to the view "produtoCodigo".
carrinho.produtoCodigo= self.produtoCodigo;
if you already pass the array to the "cartList" then remove the view "produtoCodigo" array, geter and seter (#synthesize & #property). and in the view did load you can:
produtoCodigo =[NSMutableArray arraryWithArray: self.cartList.codigo];
or if you need to use it later you can :
produtoCodigo =[NSMutableArray alloc]initWithArray: self.cartList.codigo];
and don't forget to release it later in the second option.
Hope this time it will help
shani

Related

Passing an NSMutableArray to a DetailView from UITableViewController - iPhone

I have a UITableViewController which presents another UITableViewController when a cell is tapped. I have an NSMutableArray which I want to pass into the new UITableViewController when instantiated.
I would usually do something like :
- (void)loadStationList {
StationListView * listView = [[StationListView alloc] initWithNibName:#"StationListView" bundle:nil];
listView.dataList = newParser.stationData;
// ...
// Pass the selected object to the new view controller.
NSLog(#"New Parser is %d", [newParser.stationData count]); //This is fine - all objects in array here.
[self.navigationController pushViewController:listView animated:NO];
}
The odd thing is that dataList (the NSMutableArray pointer in the new class) is empty (I am in checking in the number of rows delegate method).
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSLog(#"Data List is %d", [dataList count]);
return [dataList count];
}
I have tried several different approaches (such as instantiating a new NSMutable array in the parent class) however nothing seems to work. This may be ARC related as I am still relatively new to ARC. Can anyone help ?
How did you declare dataList,newParser.stationData ?
Should be sth like this
#property (nonatomic, strong) NSMutableArray *dataList;
Anyway, to ensure that you do not loose any values, you may want to copy/assign each element from newParser.stationData to dataList.
Like here:
NSMutableArray * dataList = [[NSMutableArray alloc] init];
for (id arrayElement in newParser.stationData) {
[dataList addObject:arrayElement];
}
Try this instead of the simple assignment listView.dataList = newParser.stationData;. ps don't worry about efficieny this is so fast it will not matter.
Well I got round this by created an instance variable in the app delegate and then saving and reading the array from there. This does look like a bug in arc - it works with other variable types.

NSArray Set property not working

Basically what i am trying to do is make a network refresh and fetch objects, store it in a nsmutable array in my app delegate. Then i have a listviewController which uses that mutable array to display data.
Setting nsarray is not working here is the code:
//Appdelegate code called after pulldown to refresh is done on listview:
[ListView setArrayElements:(NSMutableArray*)sortedArray ];
NSLog(#"sortedArray count:%d",sortedArray);
NSLog(#"ListView Array count:%d",[ListView.ArrayElements count]);
Result i get in log : "sortedArray count:12" (which is perfect)&"ListView Array count:0" (this is not the right result)
It's hard to assume without seeing more of your code but how do you define the ArrayElements property? It may not be retaining itself and you may not have initialized it when the ListView object is created.
Let me know if this works;
Make sure ArrayElements is created in your ListView.h like the following:
#property (nonatomic, retain) NSMutableArray *ArrayElements;
Or on -init or -viewDidLoad of your ListView,
self.ArrayElements = [[NSMutableArray alloc] init];
Don't forget to release what you retained:
- (void)dealloc
{
//.....
[ArrayElements release];
[super dealloc];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.mTableView reloadData];
}
use this method
Do not make the UITableView object as a property. Just use tableView object , remove 'self.' portion.
Tell me if it helps!

How many ways to pass/share data b/w view controller

im new to IOS and Objective-C and the whole MVC paradigm and i'm stuck with the following.
I am working on (replica) Contact app, also available in iphone as build in app. i want to pass data through another view controller and the data is pass (null) :(.
My Question is, How do I transfer the data from one view to another?
As most the answers you got, passing data between one controller and another just means to assign a variable from one controller to the other one.
If you have one controller to list your contacts and another one to show a contact details and the flow is starting from the list and going to detail after selecting a contact, you may assign the contact variable (may be an object from the array that is displayed in your list) and assign it to the detail view controller just before showing this one.
- (void)goToDetailViewControllerForContact:(Contact *)c
{
ContactDetailViewController *detailVC = [[[ContactDetailViewController alloc] init] autorelease];
detailVC.contact = c;
[self.navigationController pushViewController:c animated:YES];
//[self presentModalViewController:detailVC animated:YES]; //in case you don't have a navigation controller
}
On the other hand, if you want to insert a new contact from the detail controller to the list controller, I guess the best approach would be to assign the list controller as a delegate to the detail one, so when a contact is added the delegate is notified and act as expected (insert the contact to the array and reload the table view?).
#protocol ContactDelegate <NSObject>
- (void)contactWasCreated:(Contact *)c;
// - (void)contactWasDeleted:(Contact *)c; //may be useful too...
#end
#interface ContactListViewController : UIViewController <ContactDelegate>
#property (nonatomic, retain) NSArray *contacts;
...
#end
#implementation ContactListViewController
#synthesize contacts;
...
- (void)goToDetailViewControllerForContact:(Contact *)c
{
ContactDetailViewController *detailVC = [[[ContactDetailViewController alloc] init] autorelease];
detailVC.contact = c;
detailVC.delegate = self;
[self.navigationController pushViewController:c animated:YES];
//[self presentModalViewController:detailVC animated:YES]; //in case you don't have a navigation controller
}
- (void)contactWasCreated:(Contact *)c
{
self.contacts = [self.contacts arrayByAddingObject:c]; //I'm not sure this is the correct method signature...
[self reloadContacts]; //may be [self.tableView reloadData];
}
...
#end
#interface ContactDetailViewController : UIViewController
#property (nonatomic, assign) id<ContactDelegate> delegate;
...
#end
#implementation ContactDetailViewController
#synthesize delegate; //remember to don't release it on dealloc as it is an assigned property
...
- (void)createContactAction
{
Contact *c = [[[Contact alloc] init] autorelease];
[c configure];
[self.delegate contactWasCreated:c];
}
...
#end
Technically, you shouldn't!
The whole idea is not for "views" to control what happens to the data.
What you want to do is to pass data between controllers (which I imagine is exactly what you are planning to do anyway).
You can have shared model (an instance of an object that both view controllers would access) keeping the data you want to share,
You can use notifications to pass data (it is best suited for certain cases).
You can write something to disk and read it again later.
You can use NSUserDefaults.
You can use KeyChain.
...
The best way is:
declare the appropriate #property in the second view controller
when you create it, simply set the property with
viewController.property = valueYouWantToPass;
I'm a big fan of delegates and protocols.
And in some occasions use a Singleton pattern.
two ways to pass/share data between view controller
create an object and sent the data like this
QGraduteYr *tableverify=[[QGraduteYr alloc]initWithStyle:UITableViewStyleGrouped];
tableverify.mystring=myString
[self.navigationController pushViewController:tableverify animated:YES];
another method is stor it in the delegates and use it via shared delegates
MedicalAppDelegate *appdelegate=(MedicalAppDelegate *)[[UIApplication sharedApplication]delegate];
appdelegate.collnameStr=collStr;
and ust this appdelegates value whereever you need

Manage Multiple ViewControllers from a TableView

I'm curious if anyone has ideas for managing multiple ViewControllers from a TableView. I have a list of roughly seven items I am displaying in a TableView with a ViewController dedicated to each. My first thought is to initialize an array with the various ViewControllers.
NSMutableArray *viewControllers = [[NSMutableArray alloc] initWithCapacity:7];
[viewControllers addObject:[[ViewController1 alloc] initWithNibName:#"View1" bundle:nil]];
[viewControllers addObject:[[ViewController2 alloc] initWithNibName:#"View2" bundle:nil]];
...
Then reference that array to load the appropriate view on item selection.
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self.navigationController pushViewController:[viewControllers objectAtIndex:indexPath.row] animated:YES];
}
I'm really not sure if this is an appropriate approach. Any direction would be great.
EDITED:
Based on the feedback from Ryan and Joe I implemented an object to hold my table items. Abbreviating my problem also caused some confusion on implementation details. Added the full solution to manage both view controllers and selecting tab bar items.
TableNavigationItem.h
#import
#interface TableNavigationItem : NSObject {
NSString *title;
NSNumber *tabIndex;
id viewController;
}
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) NSNumber *tabIndex;
#property (nonatomic, retain) id viewController;
#end
TableNavigationItem.m
#import "TableNavigationItem.h"
#implementation TableNavigationItem
#synthesize title;
#synthesize viewController;
- (id) init{
if(self = [super init]){
self.title = #"";
}
return self;
}
- (void) dealloc {
[title release];
[tabIndex release];
[viewController release];
[super dealloc];
}
#end
Then initialize per Joe's suggestion.
NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithCapacity:7];
TableNavigationItem *navItem;
// view 1
navItem = [[TableNavigationItem alloc] init];
navItem.title = #"View 1";
navItem.tabIndex = [NSNumber numberWithInt:1];
[mutableArray addObject:navItem];
[navItem release];
// view 2
navItem = [[TableNavigationItem alloc] init];
navItem.title = #"View 2";
navItem.viewController = [ViewController2 class]];
[mutableArray addObject:navItem];
[navItem release];
...
// store the navigation items
self.tableItems = [NSArray arrayWithArray:mutableArray];
[mutableArray release];
Then
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
TableNavigationItem *navItem = [tableItems objectAtIndex:indexPath.row];
if(navItem.viewController != nil){
[self.navigationController pushViewController:[[[navItem.viewController alloc] init] autorelease] animated:YES];
}
else if(navItem.tabIndex != nil){
[((MyAppDelegate *)[UIApplication sharedApplication].delegate).tabBarController setSelectedIndex:[navItem.tabIndex integerValue]];
}
}
If all the views those controllers manage are visible on the screen immediately, there is nothing wrong with that approach. Make sure you release the array of VC's in -viewDidUnload, and recreate it in -viewDidLoad, so the runtime can unload all those extra objects when the next view is pushed onscreen. And be aware, only the root view controller will receive view lifecycle events; The view controllers you create and manually add the owned views to the table will not get those methods called. You'll have to implement some plumbing to get those view lifecycle events into the 'subviews', through notification or delegation.
The best answer to your question is "Instrument it". Run the Allocations and VM instruments at a minimum, and check to see how much memory those view controllers are consuming. If you want to improve your skillz with Instruments, watch the Performance session from WWDC 2011, they did a great job teaching how to use it to find memory and performance issues.
That sounds fine to me. The only concern I would have is whether your view controllers are RAM-heavy, in which case you may want to make a decision: is it better to preallocate everything (i.e. are you sure you can fit all of those controllers' state within available memory?) or is it better to take the latency hit to load the appropriate view controller as-needed?
It looks like your ViewControllers are of different classes. If that's the case (and if each one always uses the same respective nib), I would consider implementing a custom -init method on each and making your array of choices one of Class objects. That's just a matter of personal preference, though.
One more thing: You will want to autorelease those view controllers or you'll leak memory no matter what.

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.