[英]Is it necessary to use [unowned self] in closures of UIView.animateWithDuration(...)?
UIView.animateWithDuration(1,
animations: { [unowned self] in
self.box.center = self.boxTopRightPosition
},
completion: { [unowned self] completed in
self.box.hidden = true
})
是否有必要避免 memory 泄漏?
不,在這種情況下不需要。 animations
和completion
不被保留self
,所以沒有強烈的保留周期的風險。
好吧,“必需”與“推薦”不同。 如果您的問題是是否有必要,那么@Kirsteins的響應很好,但是請設想一下您想在完成一些工作后在視圖控制器中對某些東西進行動畫處理,但視圖控制器已被釋放的情況(因為它不再在視圖層次結構中了)或任何其他原因)。 在這種情況下,如果您不使用[weak self]
,則在完成動畫之前不會釋放視圖控制器,因為您將其保留在動畫塊中,但是將其保留直到動畫化某些東西才有意義不在視野中了嗎?
因此,簡而言之,在對UIKit進行動畫處理時, 不需要使用對自身的weak
引用,但是,如果發布了視圖,則無需保留視圖,因為沒有視圖的動畫是沒有意義的,因此使用weak
是一個不錯的選擇。
不,不需要。 正如柯斯坦斯所說:
不,在這種情況下不需要。 動畫和完成不是自己保留的,因此沒有強大的保留周期的風險。
但是lhmgrassi說:
一旦解除分配,將調用反初始化器,並且永遠不會執行完成。
我不認為這是真的。 完成模塊將始終被調用。 而且,如果您使用強大的自我,則在執行完成塊之前,不會釋放對象。
但是,如果使用[weak self]
,則完成塊不會(臨時)保留您的對象,並且可能在激發完成塊之前將其釋放。 完成塊仍被觸發,但self
已為nil
。
如果在完成處理程序中使用[unowned self]
,則在完成處理程序被調用之前,對象也可能會被釋放,這可能導致崩潰!
我已經舉例說明了這一點。
正如@Kirsteins所說,@ Plabo不會自行保留動畫和完成,因此,即使您開始動畫並且由於某種原因釋放了視圖控制器,它也會立即釋放。 因此,您不需要捕獲的“自我”。 考慮下面這個愚蠢的例子:
class ViewController: UIViewController {
@IBOutlet weak var button : UIButton!
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad ViewController")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
UIView.animate(withDuration: 20, animations: {
self.button.frame = CGRect(x: 0, y: 300, width: 30, height: 30)
}) { finished in
self.button.frame = CGRect(x: 0, y: 100, width: 30, height: 30)
}
}
deinit {
print("deinit ViewController")
}
}
一旦解除分配,將調用反初始化器,並且永遠不會執行完成。
恰好相反。 您希望 self
繼續存在足夠長的時間,以便調用完成塊。 因此具有self
堅強,通過退避完成處理保留是一件好事 。
通常導致人們使用weak self
的煩惱是一個保留周期 。 但這不是那樣。 一個保留周期時, self
保留保留了封閉self
,造成泄漏,因為現在self
可以永遠不會被釋放。 但這根本不是那種情況。 封閉,因此self
,被保留,而不是self
保留! 因此,暫時會有一些保留,但這很好 ,還不錯。
不需要在Animations,GCD或完成處理程序中使用弱/無用的,因為:
它們捕獲的外部對象引用將僅保留固定的時間 ,這意味着它將在某個時間點執行。 此后,它將被釋放,因此不會有導致內存泄漏的參考周期機會。
如先前的答案所示,
如果動畫和完成不是自己保留的,那么誰保留它們?
我沒有找到任何書面證據,但我相信它們是自己保留的,但是固定的時間里 。 此后,完成執行並釋放自我,這導致自我的取消分配。
在保留周期方案中,閉包將由self和self由閉包保留不確定的時間,這被視為參考周期和內存泄漏。
關於這個問題的許多錯誤答案。 動畫永遠不需要weak self
。
一旦您在 ViewController 上調用dismiss
,將調用 animation 完成(成功為 false),並且您的 ViewController 將被釋放,即使有很強的自引用也是如此。
通過這個測試:
class TestVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.view.alpha = 1
UIView.animate({
self.view.alpha = 0
}, duration: 40) { success in
print("finished: \(success)")
self.view.backgroundColor = .green
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
self.dismiss(animated: true)
}
}
deinit {
print("deinit")
}
}
在日志中,您將獲得:
finished: false
deinit
6 秒后
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.