views:

409

answers:

2

An iphone app I'm working on is terminating periodically ... and I have a feeling it is because of how I'm accessing a shared NSArray amongst several view controllers. So ...

What is the best way to pass NSArray/NSMutableArray amongst several ViewControllers ... all of which can modify and/or set it to nil or whatever?

Thanks

A: 

you are probably not retaining it, it gets deallocated and you are trying to access it again. try to send a [myArray retain] where you are using it (in each of the controllers), and [myArray release] when you are done with it

matei
+2  A: 

There are two approaches, generally speaking.

In the first approach, when you instantiate your next view controller, you could set an array property to "inherit" from the current (soon-to-be previous or parent) view controller:

MyNextViewController *_myNextViewController = [[MyNextViewController alloc] initWithNibName:@"MyNextViewController" bundle:nil];
_myNextViewController.myViewControllerArray = self.myViewControllerArray;
...

In the second approach, you could create a myAppDelegateArray property in your application delegate, instantiating the array when the application initializes (or instantiated somewhere else, on demand).

You can then call the getter for this property from any class — including view controllers.

For example, within an instance of MyNextViewController, you might have a property called myViewControllerArray and you would set it as follows:

self.myViewControllerArray = [UIAppDelegate myAppDelegateArray]; 

You would add a #define statement somewhere in your application constants file, e.g.:

#define UIAppDelegate ((MyAppDelegate *)[UIApplication sharedApplication].delegate)

or use the full [UIApplication sharedApplication].delegate call, if you prefer.

As a general approach, people seem to prefer the app delegate approach, as it decentralizes access to the desired property.

With this approach, if you rearrange your view controllers or insert new view controllers into your VC hierarchy, you wouldn't need to debug child view controller properties inherited from parent view controllers, because a reference is always available from the app delegate.

Alex Reynolds
I personally never recommend the "use the application delegate like a Globals.h" approach because it's not a good design technique to teach people. Using class properties to pass objects along is much more orderly.
Shaggy Frog
I'm actually interested to hear pros and cons about these designs. I'm of two minds about them and have gradated towards using the app delegate approach lately, as I reuse more of my code.
Alex Reynolds
Out of curiousity ... what is the best way to reset a shared NSArray that is being passed around? Do a release or just set to nil? Also, what is the effect if I set an NSarray = nil in Controller A IF Controller B and C have a retain on it?Thanks
wgpubs
When releasing a retained object, think of three objects with arrows pointing to a box containing the array, and then the `release` takes an eraser and erases one of the arrows. You'd still have two arrows pointing to the box. This is decreasing the "retain count", and B and C should still "retain" pointers to the array.
Alex Reynolds
I'm following approach A ... but when I remove all objects from the array in the PARENT ... they aren't removed in the CHILD. I'm using "[[self mutableArrayValueForKey:@"pictures"] removeAllObjects];". I have NSLog statements that show in the parent the count=0 AND in the child showing count != 0. Shouldn't they both be pointing at the same instance???
wgpubs
Are you making a copy of the array? Are you adding retain references in both parent and child?
Alex Reynolds
Both the parent and child view controllers define the arrays as properties (e.g. @property (nonatomic, retain) NSMutableArray *photos;). I set the parent's property doing an alloc/int and then pass that to the child as ... "childController.photos = self.photos". I believe the @property syntax is doing the retain for me.
wgpubs
The problem was that I was trying to enable KVO for changes made to my NSMutableArray (removing all objects, adding an object) but utilizing "mutableArrayValueForKey:". This does succeed in notifying other objects of a change to the NSMutableArray ... BUT it also creates a new instance and points to it rather than the original NSMutableArray.
wgpubs