1

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?

Jules
  • 7,568
  • 14
  • 102
  • 186

6 Answers6

2

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
  • 2,982
  • 1
  • 16
  • 12
  • 1
    Nooooo! Create a singleton. Don't pollute the app delegate with stuff that is not related to application-level event handling. – Josh Hinman Oct 13 '10 at 22:43
2

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
  • 15,557
  • 5
  • 43
  • 45
  • 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. Oct 13 '10 at 23:36
  • The other advantage of a class method is that it has a more obvious "owner" than some C functions floating around. – tc. Oct 13 '10 at 23:40
  • Just wondering if you find using an assert preferable to using `@synchronized`. – jlehr Oct 13 '10 at 23:42
  • 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 Oct 13 '10 at 23:44
  • @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 Oct 14 '10 at 11:14
  • @jlehr: I would use `@synchronized` since you don't have to write the logic to ensure that the main thread gets there first. – JeremyP Oct 14 '10 at 11:16
1

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

Community
  • 1
  • 1
Shiun
  • 2,677
  • 1
  • 20
  • 20
1

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
  • 603
  • 5
  • 18
0

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
  • 389
  • 3
  • 8
0

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.
  • 33,468
  • 5
  • 78
  • 96