已經有了__weak 為什麼還要保留 __unsafe_unretained ?

個人理解 __weak 和 __unsafe_unretained 的應用場景是重合的,__unsafe_unretained 會導致野指針問題,為什麼不廢棄 __unsafe_unretained ?


已經有人回答了,__unsafe_unretained 主要跟 C 代碼交互。

另外 __weak 是有代價的,需要檢查對象是否已經消亡,而為了知道是否已經消亡,自然也需要一些信息去跟蹤對象的使用情況。__unsafe_unretained 比 __weak 快。當明確知道對象的生命期時,選擇 __unsafe_unretained 會有一些性能提升。

當 A 擁有 B 對象,當 A 消亡時 B 也消亡。這樣當 B 存在,A 就一定會存在。而 B 又要調用 A 的介面時,B 就可以存儲 A 的 __unsafe_unretained 指針。

比如 MyViewController 擁有 MyView, MyView 需要調用 MyViewController 的介面。MyView 中就可以存儲 __unsafe_unretained MyViewController* _viewController。

再舉一個現實工程作為例子。

CanvasView 繼承 UIView, 用於在屏幕顯示。考慮到性能和平台無關,真正的繪圖實現是純 C++ 編寫的 gr::Canvas。CanvasView 包含 gr::Canvas,將交互操作轉發給 gr::Canvas。而 gr::Canvas 繪圖之後,需要通知 CanvasView 進行刷新。於是就需要定義一些介面作為間接層。

struct CanvasDeriver {
virtual ~CanvasDeriver() {
}

virtual void setNeedsGLDisplay(const gr::GrAABB bounds) = 0;
virtual void setNeedsRedrawLayers() = 0;
......
};

class CanvasDeriverImpl : public CanvasDeriver {
public:
void init(CanvasView* aView, EAGLContext* context) {
virtual void setNeedsRedrawLayers() override;
virtual void setNeedsGLDisplay(const gr::GrAABB bounds) override;

private:
__unsafe_unretained CanvasView* _canvas;
__unsafe_unretained EAGLContext* _context;
};

這時 CanvasView 包含 gr::Canvas 和 CanvasDeriverImpl, 將 CanvasDeriverImpl 作為間接層傳給 gr::Canvas。這樣 gr::Canvas 就可以調用介面,而 CanvasDeriverImpl 又在實現中調用 CanvasView 的介面,於是 CanvasView 就可以刷新。

而 CanvasView 消亡之後,CanvasDeriverImpl 一定會消亡。換句話說,就是 CanvasDeriverImpl 存在,CanvasView 一定會存在。這種情況下就可以使用 __unsafe_unretained,會比 __weak 要快一點。

這種性能提升是很微小的。但當我很清楚這種情況下,__unsafe_unretained 也是安全的,自然可以快一點就是一點。而當情況不確定的時候,應該優先選用 __weak 了。

同樣,使用 Swift 時,也會分 weak 和 unowned。unowned 的含義跟 __unsafe_unretained 差不多。假如很確切地知道對象的生命期,可以選擇 unowned。比如

_cancelButton.addEventHandler(for: .touchUpInside) { [unowned self] bt in
self.onButtonPressed?(.cancel)
}

在這裡,我很明確知道 _cancelButton 存在,self 一定會存在,也就可以使用 unowned。這裡選擇 unowned 並非為了性能,而只是不想寫成 self?。


看一下官方 guide 吧,從實現上講 ownership 有區別,從用途上主要是跟 C 代碼配合,哲學上這個顯示錶達了出野指針這個鍋 OC 不背的意思。


__weak是有性能開銷的,會遍歷weak表,然後把表裡的所有指針變數置你了。


推薦閱讀:

遊戲開發中的一個小問題(設計模式)?
求推薦初學者iOS開發APP學習參考書,目標兩個月內開發一個成熟的APP?

TAG:iOS開發 | iOS開發者 |