2

私は iOS / Objective C の初心者ですが、さまざまな言語で何年にもわたってプログラミングを行ってきました。

当社は既存のiOSアプリの改造を承りました。現在、plist ファイルを読み込んで、その内容を UITableView に入力しようとしています。セルを作成するコードでエラーが発生し、何が起こっているのかわかりません。

これが私のplistファイルです。非常に単純です:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <array>
        <dict>
            <key>title</key><string>Un</string>
            <key>subtitle</key><string>Subtitle</string>
        </dict>
        <dict>
            <key>title</key><string>Deux</string>
            <key>subtitle</key><string>Subtitle</string>
        </dict>
    </array>
</plist>

plist ファイルをメモリにロードする場所は次のとおりです。

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *plistCatPath = [[NSBundle mainBundle] pathForResource:@"resources" ofType:@"plist"];
    resources = [NSMutableArray arrayWithContentsOfFile:plistCatPath];
}

ここで、プロパティにアクセスしようとします。コンパイル時にエラーが発生するコメントを追加しました。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    int index = (int) indexPath.row;
    UITableViewCell *cell =[factory cellOfKind:@"cell" forTable:tableView];
    [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
    UILabel *lblTitle = (UILabel*)[cell viewWithTag:2];
    UILabel *lblSubtitle = (UILabel*)[cell viewWithTag:3];
    NSDictionary *resource = resources[index]; // incompatible types in initialization
    NSString *row_title = resource[@"title"]; // array subscript is not an integer
    NSString *row_subtitle = resource[@"subtitle"]; // array subscript is not an integer
    [lblTitle setText: row_title];
    [lblSubtitle setText: row_subtitle];
    return cell;
}
4

2 に答える 2

3

H2CO3 が言ったように、この構文は、Xcode 4.4 および 4.5 と共にリリースされた「Modern Objective-C」の一部であるオブジェクトの添え字の一部です。

数値以外の添え字については、Objective-C Literalsサイトにアクセスし、下にスクロールして「添え字メソッド」というタイトルのセクション (Apple では「ボックス化構文」または「ボックス化構文」と呼ばれることがあります) を参照してください。そこで議論した。回答の最後に他の参考文献を含めました。

最初の例は、配列内の値を検索するための配列スタイルの添え字です。

NSArray *resources = ... // however it was defined
NSDictionary *resource = resources[index];

コンパイラはこれを次のように変換します。

NSDictionary *resource = [resources objectAtIndexedSubscript:index];

マシン上の Xcode (およびコンパイラ) をアップグレードしたくない場合は、配列スタイルの添え字を従来のobjectAtIndex構文に置き換えるだけで済みます。

NSDictionary *resource = [resources objectAtIndex:index];

同様に、あなたが示した 2 番目の例は、数値以外の添字を使用したものでした。これは辞書スタイルの添え字です:

NSString *row_title = resource[@"title"];

コンパイラは次のように変換します:

NSString *row_title = [resource objectForKeyedSubscript:@"title"];

繰り返しますが、Xcode (およびそのコンパイラ) をアップグレードしたくない場合、従来の同等の方法は次のとおりです。

NSString *row_title = [resource objectForKey:@"title"];

要するに、幸運かもしれませんが、このNSArrayandの添え字の使用は、NSDictionaryこの方法に限定されています。しかし、プロジェクトは "Modern Objective-C" を使用するようにリファクタリングされており、配列リテラルなどの他の Modern Objective-C 構造が表示される場合があります。

NSArray *array = @[@"one", @"two", @"three"];

このプロジェクトのどこかにそれがある場合、古いコンパイラはその配列リテラル構文を理解できないため、次のものに置き換える必要があります。

NSArray *array = [NSArray arrayWithObjects:@"one", @"two", @"three", nil];

同様に、辞書リテラルが表示される場合があります。

NSDictionary *dictionary = @{@"key1" : @"value1", @"key2" : @"value2"};

それを次のように置き換える必要があります。

NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"value1", @"key1", @"value2", @"key2", nil];

最後に、数値リテラルも使用できます。たとえば、次のようになります。

NSNumber *number = @4;
NSNumber *done = @YES;

それは同等です

NSNumber *number = [NSNumber numberWithInt:4];
NSNumber *done = [NSNumber numberWithBool:YES];

プロジェクトに含まれる最新の Objective-C の量によっては、かなりの数の編集が必要になる場合があります。または、Xcode 4.5 以降にアップグレードできれば、問題なくこのコードをコンパイルできます。

NSDictionaryXcode 4.5 には、新しい列挙メソッド、型指定された列挙型、文字列リテラルなど、他にも非常に便利な構成要素が多数あります。Modern Objective-C に関する WWDC 2012 セッションを視聴して、自分が何であるかを理解する必要があります。古いコンパイラに固執することで見逃してしまいます。また、スタック オーバーフローや他の場所に投稿されている最新の Objective-C コードを解読する方法を理解することもできます。

詳細については、次を参照してください。

于 2012-12-06T21:56:00.790 に答える
1

これは明らかに、新しいオブジェクト リテラル構文を認識しない古いコンパイラを使用しているためです。アップグレードしたくない場合は、 と で適切なインスタンス メソッドを使用しNSArrayますNSDictionary

NSDictionary *resource = [resources objectAtIndex:index];
NSString *row_title = [resource objectForKey:@"title"];
NSString *row_subtitle = [resource objectForKey:@"subtitle"];

このアプローチを選択すると、下位互換性が維持されます。これは良いことです。

于 2012-12-06T21:25:05.397 に答える