1

我想知道当你在内存管理方面(即我想避免一个保留周期)在Swift中为一个块分配一个函数时它意味着什么。在Swift中将函数分配给块时捕获语义?

例如,假设我有如下定义按钮:

class Button { 
    var wasTapped:() -> Void 
} 

我用它在一个视图控制器像这样:

class ViewController { 
    let button: Button 

    func setUpButtonHandler() { 
    button.wasTapped = ... 
    } 

    func buttonWasTapped() { 
    // do something 
    } 
} 

我的问题是关于button.wasTapped = ...分配。

显然,如果我把它像这样:

button.wasTapped = { self.buttonWasTapped() } 

我刚刚创建了一个保留周期:视图控制器 - >按钮 - >视图控制器。

然而,斯威夫特让我做这件事,而不是:

button.wasTapped = buttonWasTapped 

它是安全的这样做呢? (即,这是否会阻止保留周期?)

回答

3

这仍然会创建保留周期。

一个好办法去想它是认识到,任何时候你看到:

button.wasTapped = buttonWasTapped 

这只是为速记:

button.wasTapped = { self.buttonWasTapped() } 

这显然会创建一个保留周期,明确使用self清楚地表明。

这很混乱,因为保留周期在第二个版本中很明显,但不是第一个。

不幸的是,这意味着你将需要坚持到更详细的(并保留周期避免):

button.wasTapped = { [weak self] in self?.buttonWasTapped() } 

您可以验证这个操场这种行为:

class Button { 
    var wasTapped:() -> Void 

    init() { 
    wasTapped = {} 
    } 
} 

class ViewController { 
    let button: Button 

    func setUpButtonHandler() { 
    //button.wasTapped = { [weak self] in self?.buttonWasTapped() } // no retain cycle 
    //button.wasTapped = { self.buttonWasTapped() } // retain cycle 
    //button.wasTapped = buttonWasTapped // retain cycle 
    } 

    func buttonWasTapped() { 
    print("tapped!") 
    } 

    init() { 
    button = Button() 
    setUpButtonHandler() 
    } 

    deinit { 
    print("deinit") 
    } 
} 

func test() { 
    let vc = ViewController() 
    vc.button.wasTapped() 
} 

test() 

更新:更多详情可以fo und here:Function references in Swift and retain cycles

+0

帮助文章:) +1 –

相关问题