0

NSValue を NSNumber に変換したい。このコードの何が問題になっていますか?

char value[4];
[myNSValue getValue:(void*)value];
NSNumber *number = [[NSNumber alloc] initWithBytes:(void*)value objCType:[myNSValue objCType]];
NSTimeInterval duration = [number intValue];

最後の行でクラッシュが発生します。ここで何が起こる可能性がありますか?

4

2 に答える 2

2

上記のコメントで @ale0xB が診断したように、実際にはメソッドNSNumber の独自の実装を提供していません。-initWithBytes:objCType:したがって、そのセレクターを呼び出すと、実際にはNSNumberの基本クラスからの実装が取得されNSValueます。と の間には1つの違いは[[NSNumber alloc] initWithBytes:foo objCType:bar]ありません[[NSValue alloc] initWithBytes:foo objCType:bar]— どちらも同じメソッドの実装を呼び出します。これは、指定された を解放し、一般にタイプ( の文書化されていないサブクラスであり、 ではありません)selfである新しいオブジェクトを返します。NSConcreteValueNSValueNSNumber

さらに明確にするために:

#import <assert.h>
#import <Foundation/Foundation.h>

int main()
{
    id x;

    x = [NSNumber numberWithInt:42];
    assert( [x isKindOfClass:[NSNumber class]] );
    assert( [x respondsToSelector:@selector(intValue)] );

    int fortytwo = 42;
    x = [[NSNumber alloc] initWithBytes:&fortytwo objCType:@encode(int)];
    assert(   [x isKindOfClass:[NSValue class]] );
    assert( ! [x isKindOfClass:[NSNumber class]] );  // yikes!
    assert( ! [x respondsToSelector:@selector(intValue)] );  // your particular problem
}

ただし、カテゴリは救助に!Martin Häcker は、NSNumber(CreatingFromArbitraryTypes)あなたがやりたいことに適応できるカテゴリーを書きました。パブリック ドメインのソース コードはこちらからご覧ください2基本的な考え方は、考えられるすべての型エンコーディングを特殊なケースにすることです。

  • をエンコードしようとしている場合は"i"、にディスパッチし-numberWithInt:ます。
  • をエンコードしようとしている場合は"f"、にディスパッチし-numberWithFloat:ます。

等々。これは面倒です。しかし、一度コードを書いたら、それ以降はカテ​​ゴリを使用して、単純に を呼び出すことができます[NSNumber numberWithValue:myNSValue]

( 1 – 多かれ少なかれ。この文脈では大きな違いはありません。)

( 2 – そのコードには、特に後のリビジョンで、いくつかのバグがあります。私のパッチはこちらを参照してください。)

于 2013-05-22T18:06:11.347 に答える
1

詳細については、上記の私のコメントをお読みください。

目的を達成するには、単に (char *) で NSString を初期化し、NSString の intValue を呼び出します。-あなたがタイプを知っていると仮定すると、そうでない場合は以下のコメントを見てください-

乾杯

于 2012-09-25T15:21:50.467 に答える