簡體   English   中英

ARC弱ivar在返回之前發布 - 在構建發布時,而不是調試

[英]ARC weak ivar released before being returned - when building for release, not debug

我有一個懶惰創建對象的類,並將其存儲為弱屬性。 其他類可能會請求此對象,但顯然必須對其進行強引用以防止對象被釋放:

// .h
@interface ObjectManager
@property(nonatomic, weak, readonly) NSObject *theObject;
@end

// .m
@interface ObjectManager ()
@property(nonatomic, weak, readwrite) NSObject *theObject;
@end

@implementation ObjectManager
- (NSObject *)theObject
{
    if (!_theObject) {
        _theObject = [[NSObject alloc] init];
        // Perform further setup of _theObject...
    }
    return _theObject;
}
@end

當方案的Xcode設置為建立調試,工作的事情就好了-一個對象可以調用objectManagerInstance.theObject並取回theObject

當計划設置為建立發布, theObject返回nil

// Build for Debug:
NSObject *object = objectManagerInstance.theObject;
// object is now pointing to theObject.

// Build for Release:
NSObject *object = objectManagerInstance.theObject;
// object is now `nil`.

我的猜測是編譯器通過在訪問器方法本身中沒有進一步使用_theObject來優化我的代碼,因此在返回之前將弱變量設置為nil 看來我必須在實際返回變量之前創建一個強引用,我只能想用塊來做,但是會很亂,我寧願避免它!

是否有某種關鍵字我可以使用返回類型來阻止ivar這么快被填滿?

最有可能的是,DEBUG構建會導致對象在自動釋放池中停留足夠長的時間以使其“工作”,而RELEASE構建會使優化器進行更多的控制流分析,從而消除自動釋放聊天。

坦率地說,編譯器沒有在發布版本中發出警告說代碼永遠無法工作是一個錯誤(請提交它,因為你有一個很棒的,簡潔的例子)!

您需要在對象的某處保持強引用,直到需要強引用有機會獲取引用。

我想知道這樣的事情是否有效:

- (NSObject *)theObject
{
    NSObject *strongObject;
    if (!_theObject) {
        strongObject = [[NSObject alloc] init];
        _theObject = strongObject;
        // Perform further setup of _theObject...
    } else {
        strongObject = _theObject;
    }
    return strongObject;
}

即上面的內容更類似於返回自動釋放對象的工廠方法,同時還在內部維護弱引用。 但優化器可能太聰明了一半而且也打破了上述情況。

你被優化器咬了。

由於_theObject是一個弱引用,系統可以自由地去除它,並且在沒有保留的情況下將你的弱引用歸零。 但是不需要馬上做。

在您的惰性實例化器中, 永遠不會保留新創建的對象。 優化器看到了這一點,並說“哇!我可以隨時將此引用歸零!為什么我不這樣做......現在!” 在你知道它之前,你將返回零。

你想要做的是將lazily-instantiated對象分配給局部變量,以獲得持久的強引用,該引用持續到函數的范圍。 您還想使用objc_precise_lifetime注釋告訴編譯器您確實需要完整的范圍。

有關標准的詳細信息, 請參閱此頁面

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM