マスター/ディテールアプリで、5つのセクションのあるTableViewを表示したい:
そこで、Xcode 5.0.2で空のマスター詳細アプリを作成し、その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
{
....
}
しかし、上記の両方の試みは私に構文エラーを与えます:
更新:
驚いたことに、この単純な質問には多くの提案がありますが、iOS/Objective-C初心者としては、どのソリューションが最も適切かはわかりません。
dispatch_once
-マルチスレッドアプリで何かを一度実行するのは、ランタイム操作ではありませんか?ここはやり過ぎではないですか? const配列を開始するためのコンパイル時のソリューションを期待していました...
viewDidLoad
-バックグラウンドとフォアグラウンドの間でアプリが変わるとき、const配列を何度も開始する必要はないでしょうか?
NSArray
にawakeFromNib
を設定したほうがよいのではないでしょうか(すべてのViewControllerにストロイボードシーンを使用しているため)。または、おそらく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];
クラスメソッドで初期化できます + initialize
static NSArray *_titles_1;
@implementation MasterViewController
+ (void)initialize {
_titles_1 = @[
@"Your Move",
@"Their Move",
@"Won Games",
@"Lost Games",
@"Options"
];
}
@end
次のようなこともできます:
static NSString * const strings[] = {
[0] = @"string_1",
[1] = @"string_2",
[2] = @"string_3",
[3] = @"string_4",
// ...
};
これはNSArray
ではありませんが、このようにNSStrings
にアクセスできますstrings[n]
@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" ]];
}
}
次の方法が良いかどうか(自分の質問に答えるのか)。
#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
クラスで)一度初期化されます。そして、self
チェックは、このメソッドが再び実行されるのを防ぎます-継承するクラスがそれ自身の+initialize
方法。
dispatch_onceは機能します。複雑な場合に機能し、単純な場合に機能します。そのため、一貫性を保つために、すべての場合に使用することをお勧めします。これにより、たとえば、すべての定数文字列をNSLocalizedString()の呼び出しに置き換えると、非常に簡単になります。コードを変更する必要はありません。
+(void)initializeで行うことは実際には間違っていませんが、実際に使用する前に最初にクラスを構成したい状況があり、もちろん、可能な構成メソッドが実行を開始する直前にinitializeが呼び出されます。また、実際にクラスコンテキストがない場合もあります。 dispatch_onceは常に機能します。
この方法でオブジェクトをインスタンス化することはできません。インターフェースでのみ宣言できます。以下をせよ:
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