web-dev-qa-db-ja.com

文字列の静的NSArray-View Controllerで初期化する方法/場所

マスター/ディテールアプリで、5つのセクションのあるTableViewを表示したい:

  1. あなたの動き
  2. 彼らの動き
  3. ゲームに勝った
  4. 失われたゲーム
  5. オプション

そこで、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
{
     ....
}

しかし、上記の両方の試みは私に構文エラーを与えます:

enter image description here

更新:

驚いたことに、この単純な質問には多くの提案がありますが、iOS/Objective-C初心者としては、どのソリューションが最も適切かはわかりません。

dispatch_once-マルチスレッドアプリで何かを一度実行するのは、ランタイム操作ではありませんか?ここはやり過ぎではないですか? const配列を開始するためのコンパイル時のソリューションを期待していました...

viewDidLoad-バックグラウンドとフォアグラウンドの間でアプリが変わるとき、const配列を何度も開始する必要はないでしょうか?

NSArrayawakeFromNibを設定したほうがよいのではないでしょうか(すべてのViewControllerにストロイボードシーンを使用しているため)。または、おそらくinitSomething(正しいメソッドinitWithStyleですか?)

46

配列を返すクラスメソッドを記述します。

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

クラスメソッドで初期化できます + initialize

static NSArray *_titles_1;

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

次のようなこともできます:

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

これはNSArrayではありませんが、このようにNSStringsにアクセスできますstrings[n]

7
Pablo A.

@implementationの上に静的配列を宣言する必要があります。

static NSArray *titles_1 = nil;

@implementation ...

そして、initまたはawakeFromNib、またはviewDidLoadapplicationDidFinishLaunchingのような他のメソッドで任意の場所で定義します。

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

    if (titles_1 == nil){
        [self setTitles_1:@[ @"Your Move", @"Their Move", @"Won Games", @"Lost Games", @"Options" ]];
    }
}
7
Anoop Vaidya

次の方法が良いかどうか(自分の質問に答えるのか)。

#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 方法。

6

dispatch_onceは機能します。複雑な場合に機能し、単純な場合に機能します。そのため、一貫性を保つために、すべての場合に使用することをお勧めします。これにより、たとえば、すべての定数文字列をNSLocalizedString()の呼び出しに置き換えると、非常に簡単になります。コードを変更する必要はありません。

+(void)initializeで行うことは実際には間違っていませんが、実際に使用する前に最初にクラスを構成したい状況があり、もちろん、可能な構成メソッドが実行を開始する直前にinitializeが呼び出されます。また、実際にクラスコンテキストがない場合もあります。 dispatch_onceは常に機能します。

2
gnasher729

この方法でオブジェクトをインスタンス化することはできません。インターフェースでのみ宣言できます。以下をせよ:

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
  • または同様に、viewDidLoadの代わりにviewcontroller initメソッドを使用できます
2