2

に格納されているオブジェクトへのポインターを取得して、NSValue変更できるようにしたいと思います。あらすじはこんな感じです。

// Get a pointer to the value's buffer (it'd be void*, I guess).
CGRect *myRect = [rectValue getPointer];

// Modify the rectangle.
myRect->origin = CGPointMake(10, 10);

NSValuemethod があることに気づきましpointerValueたが、ドキュメントには次のように記載されています。

void へのポインターとしての値。値オブジェクトがポインター サイズのデータ​​項目を保持するために作成されていない場合、結果は未定義です。

…したがって、これはポインターである値にのみ適しているようですが、これはそうではなく、CGRect.

ちなみに、答えが「あなたはこれを行うことはできません」である場合でも、私に関する限り、それはまだ良い答えです:-) APIに驚くほど明白な欠如があるように見えるので、なぜそうしないのかの説明は興味深いでしょう. .

4

1 に答える 1

1

答えは確かに「あなたにはできない」だと思います*。

なぜこのようにすべきなのかについて、いくつかの理由が考えられます。

  • NSValueは、Objective-C の多くのコア データ型と同様にimmutableです。インスタンス内に格納されている内部値へのポインターを取得できるようにすることは、その不変性にとってあまり良いことではありません。
  • そのようなポインターへのアクセスは、必然的にvoid *. これにより、コンパイラの型チェック機能がすべて回避されます。
  • 一般に、クラスは内部状態と機能を可能な限り外の世界から隠そうとし、外の世界とのやり取りを慎重に管理します。NSValue保存された値にアクセスするたびにインスタンスが認識したいというばかげたケースを想像してみてくださいCGRect(私が知る限り、NSValue実際にはこれを監視していません)。ポインターでは、いつそうするかを知ることができませんでした。ただし、方法-[NSValue CGRectValue]では、通知するしかありません。

特に最初の 2 つの理由に直面すると、自分に言い聞かせることさえあるかもしれませpointerValueん。これにより、潜在的に可変性が許可され、ポインターが型チェックされないようになる可能性があります。良い質問ですが、簡単に答えられます:ポインターを使用してNSValueインスタンスを作成する場合、たとえば を使用+[NSValue valueWithPointer:]して、そのポインターをインスタンスから戻すための唯一のオプションは、 を返すメソッドですvoid *。それ以外は、メソッド側で何らかの仮定を構成します。

* 「できない」は相対的な用語です。たとえばvalueForKey:、内部キー名がわかっている場合でも機能する可能性があります。

于 2014-12-05T22:02:58.290 に答える