Use proxy object to prevent strong reference cycle

- Closes #55
- Closes #12
This commit is contained in:
Matthew Seiler 2016-03-31 13:41:08 -04:00 committed by Reda Lemeden
parent 75220e571c
commit 367144ac1f
No known key found for this signature in database
GPG Key ID: 2A4B46ECF1B02C90
1 changed files with 22 additions and 6 deletions

View File

@ -2,11 +2,26 @@ import UIKit
/// A subclass of `UIImageView` that can be animated using an image name string or raw data. /// A subclass of `UIImageView` that can be animated using an image name string or raw data.
public class AnimatableImageView: UIImageView { public class AnimatableImageView: UIImageView {
/// Proxy object for preventing a reference cycle between the CADisplayLink and AnimatableImageView.
/// Source: http://merowing.info/2015/11/the-beauty-of-imperfection/
class TargetProxy {
private weak var target: AnimatableImageView?
init(target: AnimatableImageView) {
self.target = target
}
@objc func onScreenUpdate() {
target?.updateFrame()
}
}
/// An `Animator` instance that holds the frames of a specific image in memory. /// An `Animator` instance that holds the frames of a specific image in memory.
var animator: Animator? var animator: Animator?
/// A display link that keeps calling the `updateFrame` method on every screen refresh. /// A display link that keeps calling the `updateFrame` method on every screen refresh.
lazy var displayLink: CADisplayLink = { lazy var displayLink: CADisplayLink = {
let display = CADisplayLink(target: self, selector: #selector(updateFrame)) let display = CADisplayLink(target: TargetProxy(target: self), selector: #selector(TargetProxy.onScreenUpdate))
display.paused = true display.paused = true
return display return display
}() }()
@ -93,8 +108,9 @@ public class AnimatableImageView: UIImageView {
} }
} }
/// Invalidate the displayLink so it releases this object. /// Invalidate the displayLink so it releases its target.
deinit { deinit {
// invalidate will also remove the link from all run loops
displayLink.invalidate() displayLink.invalidate()
} }
@ -102,5 +118,5 @@ public class AnimatableImageView: UIImageView {
func attachDisplayLink() { func attachDisplayLink() {
displayLink.addToRunLoop(.mainRunLoop(), forMode: NSRunLoopCommonModes) displayLink.addToRunLoop(.mainRunLoop(), forMode: NSRunLoopCommonModes)
} }
}
}