Today, I decided that UIView animations really needed autoclosures. I felt that an in-line property assignment like this:
UIView.animate(2.0, view.backgroundColor = .blueColor())
was more aesthetically pleasing than the default syntax in the following examples, which can be written with or without trailing closures:
UIView.animateWithDuration(2.0, animations:{view.backgroundColor = .blueColor()}) UIView.animateWithDuration(2.0){ view.backgroundColor = .blueColor() }
So I built the following extension:
extension UIView { class func animate(duration : NSTimeInterval, @autoclosure _ animations : () -> Void) { UIView.animateWithDuration(duration, animations: animations) // error } }
It didn’t work, throwing a compiler error. Specifically, the complier complained that I was attempting to use a non-escaping function (the autoclosure) in an escaping context (the animateWithDuration call).
Starting in Swift 1.2, autoclosure defaults to noescape. This attribute ensures that parameters are not stored for later execution and will not outlive the lifetime of the call. Noescape implementation adds “minor performance optimizations” and bypasses the need to annotate properties and methods with “self.”.
Since animateWithDuration executes asynchronously, Since animateWithDuration hasn’t been updated to take noescaping into account, the autoclosure parameter cannot be used in its default state. Fortunately, Apple introduced an “escaping” annotation to override this limitation, solving the issue and enabling my custom animate method to work.
extension UIView { class func animate(duration : NSTimeInterval, @autoclosure(escaping) _ animations : () -> Void) { UIView.animateWithDuration(duration, animations: animations) } }
Tada.
Comments are closed.