2017-01-25 46 views
0

我在問,因爲我涉及到一些複雜的塊代碼,我不希望以下代碼正常工作。基本屬性的ivars有哪些數據類型?

說我們有一個布爾屬性,像這樣:

@property (nonatomic, assign) BOOL isCancelled; 

它的自動合成的,沒有自定義的getter,沒有setter,沒有明確的伊娃。

然後,是這段代碼......這些完美的作品

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

不過,我本來期望它的工作塊()調用,而不是爲據認爲,如果我認爲它會捕捉_isCancelled的值並保持爲const,而不是在整個執行過程中進行變異。儘管如此,在運行時,_isCancelled的值在塊內部/外部始終保持一致,就好像它實際上一樣BOOL *

任何人都可以解釋發生了什麼?

+0

在給定的代碼中沒有實際使用屬性,'_isCancelled'只是一個普通的* ivar *,儘管它是隱式聲明的。 – Sulthan

+0

同意,但由於沒有明確聲明,我可以假定它被聲明爲指針而不是原語。這可以解釋行爲(除非我錯過了某些東西) – CatalinM

+0

屬性的類型與支持ivar的類型相同。聲明'BOOL isCancelled'屬性意味着一個ivar BOOL _isCancelled將被合成。就這樣。 – Sulthan

回答

0

當聲明屬性BOOL cancelled自動合成ivarBOOL _isCancelled。這是一個原始變量,而不是指針。

但是,當一個區塊捕獲ivars時,它實際上是捕獲self,而不是ivar本身。閱讀伊娃_isCancelled其實意味着閱讀self->_isCancelled

因此,ivars不會被值捕獲,除非您先將它們保存到本地變量中(例如BOOL isCancelled = _isCancelled)。

查看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

我的問題是隨着內部塊的執行。但是,我現在明白,即使沒有直接引用,「self」實際上仍然保留。 – CatalinM

相關問題