Статический NSArray строк-как / где инициализировать в контроллере вида

в приложении Master-Detail я хотел бы отобразить TableView с 5 разделами под названием:

  1. Ваш Переезд
  2. Их
  3. Выиграл Игры
  4. Проигранных Игр
  5. опции

поэтому я создаю пустое приложение Master-Detail в Xcode 5.0.2, а затем в его MasterViewController.m (который является UITableViewController) я пытаюсь реализовать метод:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return _titles[section];
}

у меня вопрос это как init NSArray _titles?

Я пытаюсь в MasterViewController.м:

#import "MasterViewController.h"
#import "DetailViewController.h"

static NSArray *_titles_1 = @[
    @"Your Move",
    @"Their Move",
    @"Won Games",
    @"Lost Games",
    @"Options"
];

@interface MasterViewController () {
    NSMutableArray *_games;

    NSArray *_titles_2 = @[
                         @"Your Move",
                         @"Their Move",
                         @"Won Games",
                         @"Lost Games",
                         @"Options"
    ];
}
@end

@implementation MasterViewController

- (void)awakeFromNib
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
        self.clearsSelectionOnViewWillAppear = NO;
        self.preferredContentSize = CGSizeMake(320.0, 600.0);
    }
    [super awakeFromNib];
}

- (void)viewDidLoad
{
     ....
}

но обе попытки выше дают мне синтаксические ошибки:

enter image description here

обновление:

к моему удивлению, есть много предложений по этому простому вопросу, но как Новичок iOS/Objective-C я не уверен, какое решение наиболее подходит.

dispatch_once - разве это не операция выполнения, чтобы выполнить что-то один раз в многопоточное приложение? Разве это не перебор? Я ожидал решения времени компиляции для инициирования массива const...

viewDidLoad - когда мое приложение изменяется между фоном и передним планом, не было бы ненужным инициировать мой массив const снова и снова?

не должен ли я лучше установить NSArray на awakeFromNib (так как я использую сцены stroyboard для всех моих ViewControllers)? Или, может быть, в initSomething (правильный способ initWithStyle?)

8 ответов


написать метод класса, который возвращает массив.

+ (NSArray *)titles
{
    static NSArray *_titles;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _titles = @[@"Your Move",
                    @"Their Move",
                    @"Won Games",
                    @"Lost Games",
                    @"Options"];
    });
    return _titles;
}

затем вы можете получить к нему доступ, где это необходимо, например:

NSArray *titles = [[self class] titles];

вы можете init его в методе класса +инициализировать

static NSArray *_titles_1;

@implementation MasterViewController
+ (void)initialize {
    _titles_1 = @[
        @"Your Move",
        @"Their Move",
        @"Won Games",
        @"Lost Games",
        @"Options"
    ];
}
@end

вы должны объявить статический массив выше @implementation.

static NSArray *titles_1 = nil;

@implementation ...

и определить его в init или awakeFromNib или любой другой способ как viewDidLoad, applicationDidFinishLaunching куда хочешь.

- (void)initMethod{ //change the method name accordingly

    if (titles_1 == nil){
        [self setTitles_1:@[ @"Your Move", @"Their Move", @"Won Games", @"Lost Games", @"Options" ]];
    }
}

вы также можете сделать что-то вроде этого:

static NSString * const strings[] = {
        [0] = @"string_1",
        [1] = @"string_2",
        [2] = @"string_3",
        [3] = @"string_4",
        // ...
    };

это не NSArray но вы можете получить доступ к NSStrings такой strings[n]


интересно, если бы следующий был хорошим способом (отвечая на мой собственный вопрос):

#import "MasterViewController.h"
#import "DetailViewController.h"

static const NSArray *_titles;

@interface MasterViewController () {
    NSMutableArray *_objects;
    NSMutableArray *_yourMove;
    NSMutableArray *_theirMove;
    NSMutableArray *_wonGames;
    NSMutableArray *_lostGames;
    NSMutableArray *_options;
}
@end

@implementation MasterViewController

+ (void)initialize
{
    // do not run for derived classes
    if (self != [MasterViewController class])
        return;

    _titles = @[
        @"Your Move",
        @"Their Move",
        @"Won Games",
        @"Lost Games",
        @"Options"
    ];
}

сюда const NSArray это initalized раз и прямо перед мне нужно (в MasterViewController класс). И self check предотвращает повторный запуск этого метода-когда некоторый наследующий класс не реализует свой собственный +initialize метод.


вы не можете создавать экземпляры объектов таким образом, вы можете объявлять их только в интерфейсах. Сделайте следующее:

static NSArray *_titles_2;

@interface MasterViewController () {
    NSMutableArray *_games;
}
@end

@implementation MasterViewController
-(void)viewDidLoad()
{
     _titles_2 = @[
                         @"Your Move",
                         @"Their Move",
                         @"Won Games",
                         @"Lost Games",
                         @"Options"
    ];
}
@end
  • или аналогично вы можете использовать метод init viewcontroller вместо viewDidLoad

dispatch_once работ. Он работает в сложных случаях, и он работает в простых случаях. Поэтому, чтобы быть последовательным, лучше всего использовать его во всех случаях. Это делает его, например, намного проще, когда вы заменяете все свои постоянные строки вызовами NSLocalizedString (). Изменение кода не требуется.

делать что-то в + (void)initialize не совсем неправильно, но у меня были ситуации, когда я сначала хотел настроить класс, прежде чем действительно использовать его, и initialize, конечно, называется непосредственно перед тем, как любой возможный метод конфигурации начнет выполняться. И есть ситуации, когда у вас действительно нет контекста класса. dispatch_once всегда будет работать.


Я предпочитаю использовать Objective-C++, изменить имя файла с xxx.m to xxx.mm, и инициализация NSArray произойдет во время выполнения

нет dispatch_once,нет метод класса, просто напишите его в одной строке:

static NSArray *const a = @[@"a",@"b",@"c"];