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:
- Twój Ruch
- Ich Ruch
- Wygrane Mecze
- Lost Games
- 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:
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
?)
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];
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
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" ]];
}
}
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]
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
.
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
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ć.
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"];
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