tony
tony

Reputation: 160

What's wrong with and extern NSMutableArray?

So I've been doing a lot of reading. And I have been able to finally declare an extern MutableArray and access it from different Views. I have two views: 1) Testing View Controller 2) Test2

I declare the array as follows: TestingViewController.h

extern NSMutableArray *myArray;

#import <UIKit/UIKit.h>

@interface TestingViewController : UIViewController {

}

I initialize the array when the TestingViewController Loads. Then I can add Objects to it from Test 2 as Follows: Test2.m

#import "Test2.h"

NSMutableArray *myArray;
@implementation Test2

-(IBAction)addToArray{
 [myArray addObject:@"Hot like Mexico"];
 NSLog(@"Object was added to Array! Count: %d",[myArray count]);
}

It seems to be working from both Views. The count and Objects are consistant even while switching.

What I want to know is, what is wrong with this? I know a lot of experienced programmers hate global variables, but the only way I've gotten it to work is like above and through the AppDelegate (Don't want to do it that way). Just trying to be more efficient with adding and manipulating arrays from multiple Views.

Thank you guys!

Upvotes: 2

Views: 943

Answers (4)

JeremyP
JeremyP

Reputation: 86651

If you really need a "global" object, here's a simple pattern that I use quite a lot - well, not a lot, because I don't tend to have many globals.

Decide which class you want it to belong to. Let's say Test2 is the logical class to put it in. Create a method in Test2 to access the variable. (could be a class method or an instance method) as follows:

@interface Test2 : NSObject
{
    // ivars
}

+(NSMutableArray*) myArray;  // could also be an instance method

@end

@implementation Test2

+(NSMutableArray*) myArray
{
    static NSMutableArray* theValue = nil;
    @synchronized([Test2 class]) // in a single threaded app you can omit the sync block
    {
        if (theValue == nil)
        {
            theValue = [[NSMutableArray alloc] init];
        }
    }
    return theValue;
}
@end

Edit: Using the class method, to access myArray from anywhere just do this:

#import "Test2.h"

// To use class method, send messages to the class itself

[[Test2 myArray] addObject: @"foo bar"];
id foo = [[Test2 myArray] objectAtIndex: 0];

Upvotes: 2

Mark Bessey
Mark Bessey

Reputation: 19782

The problem with global variables is that they proliferate. First you have one, then you need another one, and before you know it, you've got dozens of global variables, you're not sure where variables get initialized and freed, and every change takes forever, because you don't know what the dependencies between components are.

Typically, you'll want to have an identified owner for each resource in the program. In a Cocoa app, the various controller and delegate objects provide a natural hierarchy of responsibility for various parts of the design.


For the specific case where you have an object which you need to be accessible in several views of your app, You'd typically make that object available through a method of your view controller class, then ensure that each view has a reference back to the controller.

For an example, look at any of the examples for UITableView. There is a fairly complicated data source protocol used there, but other UIKit classes have a "delegate" property which typically gets initialized to an object that manages some part of their state for them.

Upvotes: 1

amattn
amattn

Reputation: 10065

Sounds like you need a singleton. http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html

Upvotes: 1

indragie
indragie

Reputation: 18122

Global variables are nightmares when it come to memory management, and this really isn't the typical way to do things in terms of design. The proper way to do it would be to declare myArray as a property in TestingViewController and then access that property from Test2.

Upvotes: 1

Related Questions