ios objective-c nsmutablearray initialization nsarray

ios - NSArray estático de cadenas: cómo/dónde inicializar en un controlador de visualización



objective-c nsmutablearray (8)

Deberías declarar tu matriz estática arriba @implementation .

static NSArray *titles_1 = nil; @implementation ...

Y awakeFromNib en init o awakeFromNib o cualquier otro método como viewDidLoad , applicationDidFinishLaunching donde quieras.

- (void)initMethod{ //change the method name accordingly if (titles_1 == nil){ [self setTitles_1:@[ @"Your Move", @"Their Move", @"Won Games", @"Lost Games", @"Options" ]]; } }

En una aplicación de detalles maestros me gustaría mostrar un TableView con 5 secciones tituladas:

  1. Su movimiento
  2. Su movimiento
  3. Juegos ganados
  4. Juegos perdidos
  5. Opciones

Así que creo una aplicación Master-Detail en blanco en Xcode 5.0.2 y luego en su MasterViewController.m (que es un UITableViewController) estoy tratando de implementar el método:

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

Mi pregunta es, sin embargo, cómo iniciar los NG_títulos de NSArray.

Lo estoy intentando en 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 { .... }

pero ambos intentos anteriores me dan errores de sintaxis:

ACTUALIZAR:

Para mi sorpresa, hay muchas sugerencias para esta simple pregunta, pero como novato iOS / Objective-C no estoy seguro, qué solución es la más adecuada.

dispatch_once : ¿no es una operación en tiempo de ejecución ejecutar algo una vez en una aplicación de subprocesos múltiples? ¿No es excesivo aquí? Esperaba una solución en tiempo de compilación para iniciar una matriz de const ...

viewDidLoad : cuando mi aplicación cambia entre el fondo y el primer plano, ¿no sería innecesario iniciar mi matriz de const una y otra vez?

¿No debería configurar mejor el NSArray en awakeFromNib (ya que uso escenas de stroboard para todos mis ViewControllers)? O tal vez en initSomething (¿es el método correcto initWithStyle ?)


Escriba un método de clase que devuelva la matriz.

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

Entonces puedes acceder a él cuando sea necesario, así:

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


Me pregunto si la siguiente sería una buena manera (respondiendo mi propia pregunta):

#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" ]; }

De esta forma, el const NSArray se inicia una vez y justo antes de que lo necesite (en la clase MasterViewController ). Y la self evita que este método se ejecute nuevamente, cuando alguna clase que hereda no implementa su propio método +initialize .


No puede instanciar objetos de esta manera, solo puede declararlos en interfaces. Haz lo siguiente:

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

  • o del mismo modo, podrías usar el método init viewcontroller en lugar de viewDidLoad

Prefiero usar Objective-C ++, cambiar el nombre de archivo de xxx.m a xxx.mm , y la inicialización de NSArray ocurrirá en tiempo de ejecución

sin dispatch_once , no hay método de clase, solo escríbelo en una línea:

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


Puedes iniciarlo en el método de clase +initialize

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


También puedes hacer algo como esto:

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

No es un NSArray pero puedes acceder a NSStrings como este strings[n]


dispatch_once funciona. Funciona en casos complicados, y funciona en casos simples. Entonces, para ser coherente, lo mejor es usarlo en todos los casos. Eso hace, por ejemplo, mucho más fácil cuando reemplaza todas las cadenas constantes con llamadas a NSLocalizedString (). No es necesario cambiar el código.

Hacer cosas en + (nulo) initialize no es realmente incorrecto, pero he tenido situaciones en las que primero quería configurar una clase antes de usarla realmente, y la inicialización se llama, por supuesto, justo antes de que se inicie la ejecución de cualquier posible método de configuración. Y hay situaciones en las que realmente no tienes un contexto de clase. dispatch_once siempre funcionará.