2

Xcode 4.1 では意図したとおりに機能したが、Xcode 4.2 では機能しなくなった、非常に単純なコードです。問題のあるコードは次のとおりです。

-(void)mergeDevData2Email:(NSMutableString *)target codeArray:(NSArray *)array1 valueArray:(NSArray *)array2 {
NSUInteger n = 0;

for (NSMutableString *aCode in array1) {
    if ([array2 count] > n) {
        NSMutableString *arg = [array2 objectAtIndex:(NSUInteger)n];

        NSLog(@"Target isKindOf NSMutableString: %@", ([target isKindOfClass:[NSMutableString class]]) ? @"YES" :@"NO");
        NSLog(@"aCode isKindOf NSMutableString: %@", ([aCode isKindOfClass:[NSMutableString class]]) ? @"YES" :@"NO");
        NSLog(@"arg isKindOf NSMutableString: %@", ([arg isKindOfClass:[NSMutableString class]]) ? @"YES" :@"NO");

        [target replaceOccurrencesOfString:aCode withString:arg options:NSLiteralSearch range:NSMakeRange(0, [target length])];
        n++;
    }
    else {
        break;
    }
}
}

これは、NSLogs が表示するものです。

2011-11-03 15:42:59.967 TestProg[30413:c503] ターゲット isKindOf NSMutableString: はい

2011-11-03 15:42:59.968 TestProg[30413:c503] aCode isKindOf NSMutableString: はい

2011-11-03 15:42:59.969 TestProg[30413:c503] arg isKindOf NSMutableString: はい

[target replaceOcurances... コード行を実行すると、クラッシュします-

プログラム受信シグナル: "SIGABRT"。

コンソールログに次のように表示されます-

2011-11-03 15:43:26.828 TestProg[30413:c503] *キャッチされていない例外 'NSInvalidArgumentException' が原因でアプリを終了しています。

私の質問は、不変オブジェクトを変更しようとしている場所はどこですか? 第二に、これが Xcode 4.1 でうまく実行されたのはなぜですか? 確かに、すべてのプレイヤーは Xcode 4.1 に対して変更可能に見えました。Xcode 4.2 の違いは何ですか? ここで微妙なものが欠けています。

4

3 に答える 3

3

一部の文字列は実際には変更可能な文字列ではないと思われます (これは変更しようとしている文字列であるため、おそらく「ターゲット」です)。これにもしばらく戸惑いましたが、「isKindOf:」は変更可能な文字列と変更不可能な文字列を区別しません。文字列が可変でない場合でも、NSLog クエリは YES を返すと思います。

デバッガーで停止すると、オブジェクトを調べて、それらが本当に変更可能かどうかを判断できるはずです (「実際の」クラス名がオブジェクトと共に表示されるはずです)。

これが 4.2 ではなく 4.1 で機能した理由については、言うのが難しいです。NSString を返す一部のシステム ルーチンが以前は NSMutableString を返していたが、現在は返していない可能性があります。

私が正しければ、スタックを上って、ターゲットがどこから来たのかを調べる必要があります。ある時点で、NSString から NSMutableString にキャストされた可能性があります。

于 2011-11-03T23:30:19.533 に答える
0

isKindOfClass:については Apple ドキュメントを確認してください。

基本的に、クラスクラスターに対してこの種のチェックを使用しないでくださいと言い、続けて言います

クラス クラスタを返すメソッドを呼び出す場合、メソッドによって返される正確な型は、そのオブジェクトで何ができるかを示す最良の指標です。

このインスタンスのクラス クラスタから返される型が SDK 間で変更された可能性は十分にあります。

于 2011-11-03T23:30:02.937 に答える
0

「ターゲット」に渡された変数は、NSMutableString として定義され、あらゆる場所で使用されました。議論中のメソッドの前に呼び出されるメソッドの 1 つの場所で、変数はファイルの内容からロードされ、そのメソッドで、経験不足から次のステートメントを使用しました。

self.messageBody = fileContents;

fileContents は NSString でした。おっとっと。

これは明らかに、別のメモリ アドレスを持つ messageBody の新しいメモリ ロケーションを作成し、Mutable ではありませんでした。質問-それは実際に新しいオブジェクトになりますか? もしそうなら、最初のインスタンスを解放できなくなったため、メモリリークも発生したと思います。

そのため、議論中のメソッドを実行すると、「ターゲット」によって参照されるオブジェクトが Mutable ではなくなり、replaceOccurancesOfString ステートメントがクラッシュしました。

これは、Xcode 4.1 で期待どおりに実行されたが、Xcode 4.2 で適切にクラッシュした理由の異常には答えません。私がこれにたどり着いたのは、ロンの建設的な勧めのおかげです。Thxが与えられました。

于 2011-11-04T06:19:55.943 に答える