Statyczne NSArray łańcuchów-jak / gdzie zainicjować w kontrolerze widoku

W aplikacji Master-Detail chciałbym wyświetlić widok TableView z 5 sekcjami zatytułowanymi:

  1. Twój Ruch
  2. Ich Ruch
  3. Wygrane Mecze
  4. Lost Games
  5. Opcje

Więc utworzyć pustą aplikację Master-Detail w Xcode 5.0.2, a następnie w jego MasterViewController.m (który jest UITableViewController) próbuję zaimplementować metodę:

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

Moje pytanie jest jednak jak init NSArray _titles?

Staram się 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
{
     ....
}

Ale obie powyższe próby dają mi błędy składni:

Tutaj wpisz opis obrazka

UPDATE:

Ku mojemu zaskoczeniu istnieje wiele sugestii na to proste pytanie, ale jako początkujący iOS / Objective-C nie jestem pewien, które rozwiązanie jest najbardziej odpowiednie.

dispatch_once - czy nie jest to operacja runtime, aby wykonać coś raz w aplikacji wielowątkowej? Czy to nie przesada? Spodziewałem się rozwiązania w czasie kompilacji do inicjowania const / align = "left" / ..

viewDidLoad - gdy moja aplikacja zmienia się między tłem i pierwszym planem, czy nie byłoby to niepotrzebne inicjować moją tablicę const ponownie i ponownie?

Nie powinienem lepiej ustawić NSArray w awakeFromNib (ponieważ używam stroyboard scen dla wszystkich moich kontrolerów widoku)? A może w initSomething (czy prawidłowa metoda initWithStyle?)

Author: Alexander Farber, 2013-12-12

8 answers

Napisz metodę klasy, która zwraca tablicę.

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

Następnie można uzyskać do niego dostęp wszędzie tam, gdzie jest to potrzebne, jak TAK:

NSArray *titles = [[self class] titles];
 78
Author: jlehr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-12 13:26:03

Możesz go init w klasie Metoda +initialize

static NSArray *_titles_1;

@implementation MasterViewController
+ (void)initialize {
    _titles_1 = @[
        @"Your Move",
        @"Their Move",
        @"Won Games",
        @"Lost Games",
        @"Options"
    ];
}
@end
 12
Author: Emmanuel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-12 13:43:46

Powinieneś zadeklarować swoją tablicę statyczną powyżej @implementation.

static NSArray *titles_1 = nil;

@implementation ...

I zdefiniuj go w init lub awakeFromNib lub innej metodzie takiej jak viewDidLoad, applicationDidFinishLaunching gdziekolwiek chcesz.

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

    if (titles_1 == nil){
        [self setTitles_1:@[ @"Your Move", @"Their Move", @"Won Games", @"Lost Games", @"Options" ]];
    }
}
 7
Author: Forgot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-12 13:27:20

Możesz też zrobić coś takiego:

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

To nie jest NSArray ale możesz uzyskać dostęp NSStrings w ten sposób strings[n]

 7
Author: Pablo A.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-13 20:51:43

Zastanawiam się, czy poniższy sposób byłby dobry (odpowiadając na moje własne pytanie):

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

W ten sposób const NSArray jest initalizowana raz i tuż przed potrzebą (w klasie MasterViewController). A sprawdzanie self zapobiega ponownemu uruchomieniu tej metody - gdy jakaś dziedzicząca klasa nie implementuje własnej metody +initialize.

 6
Author: Alexander Farber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-13 12:48:51

Nie można tworzyć instancji obiektów w ten sposób, można je deklarować tylko w interfejsach. Wykonaj następujące czynności:

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
  • lub podobnie można użyć metody init viewcontroller zamiast viewDidLoad
 2
Author: Simon McLoughlin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-12 13:34:52

Dispatch_once działa. Działa w skomplikowanych przypadkach i działa w prostych przypadkach. Aby być konsekwentnym, najlepiej jest go używać we wszystkich przypadkach. Ułatwia to na przykład zastąpienie wszystkich ciągów ciągów wywołaniami nslocalizedstring (). Nie trzeba zmieniać kodu.

Robienie rzeczy w + (void)initialize nie jest tak naprawdę złe, ale miałem sytuacje, w których najpierw chciałem skonfigurować klasę przed jej użyciem, a initialize jest oczywiście wywoływane tuż przed każda możliwa metoda konfiguracji rozpocznie wykonywanie. I są sytuacje, w których nie masz kontekstu klasowego. dispatch_once zawsze będzie działać.

 2
Author: gnasher729,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-17 14:21:43

Wolę używać Objective-C++, zmienić nazwę pliku z xxx.m na xxx.mm, a inicjalizacja NSArray nastąpi w runtime

Nie. dispatch_once, nie metoda klasy, wystarczy napisać ją w jednej linijce:

static NSArray *const a = @[@"a",@"b",@"c"];
 0
Author: rpstw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-06 04:26:22