2017-01-25 19 views
0

私はいくつかの複雑なブロックコードを手に入れていたので、次のコードが正しく動作することを期待していなかったので、私は尋ねています。 プリミティブプロパティにはどのようなデータ型がありますか?

はように、我々はBOOLプロパティを持っていると言う:

@property (nonatomic, assign) BOOL isCancelled; 

それの自動合成し、無カスタムゲッター、セッターがない、明示的なIVAR。

その後、完全に

dispatch_async(queue, ^{ 
    id result = block(&_isCancelled); 
    if (!_isCancelled) { ... } 
} 

しかし、私はそれがブロック()の呼び出しのためではなく、私はそれをキャプチャするだろうと思ったところ、場合のために働くと予想しているだろうに動作し、このコードは...あります_isCancelledの値をconstにしておき、実行中に突然変異させることはありません。それでも、実行時に、_isCancelledの値は、実際にBOOLであるかのように、ブロックの内側/外側で常に一貫しています。*

誰でも何が起こっているのか説明できますか?

+0

実際には、指定されたコードではプロパティが使用されません。暗黙的に宣言されていますが、 '_isCancelled'は通常の* ivar *です。 – Sulthan

+0

合意されていますが、明示的に宣言されていないため、プリミティブではなくポインタとして宣言することができます。これは行動を説明することができます(私が何かを逃していない限り) – CatalinM

+0

プロパティのタイプは、裏地ivarのタイプと同じです。宣言プロパティ 'BOOL isCancelled'は、' BOOL _isCancelled'のivarが合成されることを意味します。それで全部です。 – Sulthan

答えて

0

プロパティを宣言するときBOOL cancelled自動合成ivarBOOL _isCancelledです。これはポインタではなく、プリミティブ変数です。

しかし、ブロックがivarsをキャプチャしているとき、それは実際にはivar自体ではなくselfをキャプチャしています。読み込みiver _isCancelledは実際にはself->_isCancelledを意味します。

したがって、ローカル変数に最初に保存しない限り(例:BOOL isCancelled = _isCancelled)、ivarsは値で取り込まれません。

詳細については、Block automatic retaining, does it affect even to ivars in self?を参照してください。

0

TL; DR:プロパティと同じタイプ。

すべてのオブジェクトポインタとプリミティブ型は、スカラー値です。つまり、特異値です。それらはすべてメモリ内のアドレスに格納する必要があるため、すべてが自分のメモリアドレスを持っています。

&_isCancelledを渡すことによって、あなたはBOOL変数のアドレスを渡しているので、block()は「秘密の上で聞かせて」されています - BOOLのすなわち場所 - それは、それを更新することができます。その後、の実際のの値が_isConnectedであることを確認しています。これは、プリミティブ型(スカラー)とオブジェクトポインタ(スカラーも)で動作します。

プロパティの有無は関係ありません。

+0

それは私も同様です。私は '_isCancelled'がブロック内で不変であることを期待していました(スコープ内のすべての変数を_const_として扱うので、ブロックが評価されたときの値を常に持ちます)。しかし、私はこの動作が '_isConnected'がグローバルでスコープのローカルではないという事実と関係していると考えています。 – CatalinM

+0

あなたが渡している値は_is_ constです。これはBOOLのアドレスです。コードブロックから文字どおりにそのアドレスのビットを変更することは何も変わりません。変数がBOOLではないブロックの内部では、BOOLへのポインタです。 – norders

+0

私の問題は、インナーブロックの実行に続いてifが原因でした。しかし、私は今、直接参照されていなくても、「自己」が実際に保持されていることを理解しています。 – CatalinM

関連する問題