string的静态NSArray – 在视图控制器中如何/在哪里初始化

在一个Master-Detail应用程序中,我想显示一个带有5个部分的TableView:

  1. 你的举动
  2. 他们的移动
  3. 赢得游戏
  4. 迷失的游戏
  5. 选项

所以我在Xcode 5.0.2中创build一个空白的Master-Detail应用程序,然后在它的MasterViewController.m(这是一个UITableViewController)我试图实现该方法:

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

我的问题是如何启动NSArray _titles?

我想在MasterViewController.m中:

 #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 { .... } 

但两个尝试上面给我的语法错误:

在这里输入图像说明

更新:

令我惊讶的是,对于这个简单的问题有很多build议,但作为一个iOS / Objective-C的新手,我不确定哪种解决scheme最合适。

dispatch_once – 是不是一个运行时操作在一个multithreading应用程序中执行一次? 这不是矫枉过正吗? 我期待一个编译时解决scheme来启动一个常量数组…

viewDidLoad – 当我的应用程序在背景和前景之间变化时,是不是不必要一次又一次地启动我的const数组?

难道我不应该更好地设置在awakeFromNib NSArray (因为我使用我所有的ViewControllers stroyboard场景)? 或者也许在initSomething (是正确的方法initWithStyle ?)

编写一个返回数组的类方法。

 + (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]; 

你可以在类方法初始化中初始化它

 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 ... 

并定义它在initawakeFromNib或任何其他方法,如viewDidLoadapplicationDidFinishLaunching任何你想要的。

 - (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但你可以像这样的strings[n]访问NSStrings

我想知道,如果以下是一个好方法(回答我自己的问题):

 #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在我需要之前就已经MasterViewController了(在MasterViewController类中)。 而self防止这种方法再次运行 – 当一些inheritance类没有实现自己的+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 
  • 或者也可以使用viewcontroller init方法而不是viewDidLoad

dispatch_once的作品。 它在复杂的情况下工作,并在简单的情况下工作。 所以要一致,最好的办法就是在所有情况下使用它。 例如,当你用NSLocalizedString()的调用来replace所有的常量string时,这样做会更容易一些。 无需更改代码。

在+(void)中进行初始化并不是真的错,但是在实际使用它之前,我曾经想过要configuration一个类,初始化当然是在任何可能的configuration方法开始执行之前调用的。 而且有些情况下你并没有真正的课堂背景。 dispatch_once将一直工作。

我更喜欢使用Objective-C ++,将文件名从xxx.m更改为xxx.mm ,并且NSArray的初始化将在运行时发生

没有 dispatch_once没有类的方法,只写在一行:

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