views:

95

answers:

6

I have the following array.

    NSArray *arrayDisplay = [[NSArray alloc] initWithObjects:@"Daily", 
        @"Weekly", @"Monthly", nil];

I need to use it in two views, I'm concerned that I may make changes and forget to change the other in the future. So I'd like to declare it once and reuse it.

How should I do this?

+2  A: 

You can keep it as a property in a common object such as the application delegate.

Assuming its nonatomic,retain type property then access it like:

myAppDelegate *del = [[UIApplication sharedApplication] delegate];
del.arrayDisplay = [NSArray arrayWithObjects:@"Daily",@"Weekly", @"Monthly", nil];

Although if you plan on changing it you might want an NSMutableArray.

Ben
Nooooo! Create a singleton. Don't pollute the app delegate with stuff that is not related to application-level event handling.
Josh Hinman
A fine point. Singleton would be more elegant.
Ben
The "true" singleton is almost always wrong...
tc.
A: 

You could save the array as a plist in your project and load it in each place where it's needed with

NSArray *arrayDisplay = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"myArrayName" ofType:@"plist"]];

This will work as long as you do not need to change the values in both place while the program is actually running.

trevorsm
+1  A: 

If your application is simple, consider the Singleton model where the data you are accessing are accessible through the global instance of the singleton. link text

Shiun
+2  A: 

Consider writing a class method or even a C function that lazily creates the array. For example, here's a class method that does what you want:

+ (NSArray *)frequencyChoices
{
    static NSArray *choices;

    if (choices == nil)
    {
        choices = [[NSArray alloc] initWithObjects:
                   @"Daily", @"Weekly", @"Monthly", nil]; 
    }

    return choices;
}

Writing the same functionality as a C function makes it even more general:

NSArray *frequencyChoices(void)
{
    static NSArray *choices;

    if (choices == nil)
    {
        choices = [[NSArray alloc] initWithObjects:
                   @"Daily", @"Weekly", @"Monthly", nil]; 
    }

    return choices;
}

The advantage of a class method though, is that you could override it in a subclass if that might ever prove handy.

jlehr
When doing stuff like this, I recommend `assert([NSThread isMainThread]);` unless you expect to call it from multiple threads (in which case you need to make it thread-safe).
tc.
The other advantage of a class method is that it has a more obvious "owner" than some C functions floating around.
tc.
Just wondering if you find using an assert preferable to using `@synchronized`.
jlehr
The notion of ownership is useful when there's some actual association between the functionality and the class; otherwise, I think the function's a better fit.
jlehr
@tc: In this case it doesn't matter since the array and all its content is immutable. In the worst case scenario, if several threads do the test and create the array simultaneously, the application leaks n - 1 copies of the array, where n is the number of threads that in the race condition.
JeremyP
@jlehr: I would use `@synchronized` since you don't have to write the logic to ensure that the main thread gets there first.
JeremyP
+1  A: 

Rather than using a Singleton approach, consider determining which object in your app's object hierarchy should own this array, and then pass that reference down to where it's needed (see: dependency injection).

David Cairns
A: 

If you don't mind global variables, you can instantiate them at load time:

@interface FooClass : ... {
  ...
}

static NSArray * FooClass_timescale;

@end


@implementation FooClass

+(void)load {
  FooClass_timescale = [[NSArray alloc] initWithObjects:@"Daily", @"Weekly", @"Monthly", nil]; 
}

@end

I prefer doing this when there are a pile of things I want to instantiate (e.g. colours for a theme/skin/brand/whatever), since it's shorter than writing a function to return them. Of course, it's possible to accidentally modify the global variable, but I've never managed this (usually I just forget to retain).

tc.