<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>Just because self is used in a a closure doesn’t mean a retain cycle has been created. I don’t worry about retain cycles usually, but always make sure to run my app through the Memory instrument before release, since that should detect any cycles that are present.<div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>That said, it would be very nice if Swift had an elegant solution here.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Jon</div><div class=""><br class=""></div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Aug 30, 2017, at 6:45 PM, Yvo van Beek via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">When I'm writing code I like it to be free from any distractions that aren't really relevant to the problem that I'm trying to solve. One of these distractions is having to pay a lot of attention to retain cycles. As my code grows, I start making extensions to simplify my code.</div><div class=""><br class=""></div><div class="">I've created the following helper for DispatchQueues:</div><div class=""><br class=""></div><div class=""> <font face="monospace, monospace" class=""> <font color="#3d85c6" class="">extension DispatchQueue {</font></font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> func async<T: AnyObject>(weak arg: T, execute: @escaping (T) -> Void) {</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> async { [weak arg] in</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> if let argRef = arg { execute(argRef) }</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> }</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> }</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> }</font></div><div class=""><br class=""></div><div class="">It allows you to do this:</div><div class=""><br class=""></div><div class=""> <font face="monospace, monospace" color="#3d85c6" class="">DispatchQueue.main.async(weak: self) { me in</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> me.updateSomePartOfUI()</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> }</font></div><div class=""><br class=""></div><div class="">When functions are passed as a closure, the compiler won't warn about a possible retain cycle (there is no need to prefix with self). That's why I've also created helpers for calling instance functions:</div><div class=""><br class=""></div><div class=""> <font face="monospace, monospace" color="#3d85c6" class="">func blockFor<Target: AnyObject>(_ target: Target, method: @escaping (Target) -> () -> Void) -> () -> Void {</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> return { [weak target] in</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> if let targetRef = target { method(targetRef)() }</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> }</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> }</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""><br class=""></font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> func blockFor<Target: AnyObject, Args>(_ target: Target, method: @escaping (Target) -> (Args) -> Void, args: Args) -> () -> Void {</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> return { [weak target] in</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> if let targetRef = target { method(targetRef)(args) }</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> }</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> }</font></div><div class=""><br class=""></div><div class="">Calls look like this:</div><div class=""><br class=""></div><div class=""> <font face="monospace, monospace" color="#3d85c6" class=""> class MyClass {</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> func start() {</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> performAction(completion: blockFor(self, method: MyClass.done))</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> }</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""><br class=""></font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> func done() {</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> ...</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> }</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> }</font></div><div class=""><br class=""></div><div class="">When you look at code samples online or when I'm reviewing code of colleagues this seems a real issue. A lot of people probably aren't aware of the vast amounts of memory that will never be released (until their apps start crashing). I see people just adding <font face="monospace, monospace" color="#3d85c6" class="">self.</font> to silence the complier :(</div><div class=""><br class=""></div><div class="">I'm wondering what can be done to make this easier for developers. Maybe introduce a 'guard' keyword for closures which skips the whole closure if the instances aren't around anymore. Since guard is a new keyword in this context it shouldn't break any code?</div><div class=""><br class=""></div><div class=""> <font face="monospace, monospace" color="#3d85c6" class="">DispatchQueue.main.async { [guard self] in</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> self.updateSomePartOfUI()</font></div><div class=""><font face="monospace, monospace" color="#3d85c6" class=""> }</font></div><div class=""><br class=""></div><div class="">I don't have any ideas yet for a better way to pass functions as closures.</div><div class=""><br class=""></div><div class="">- Yvo</div></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></div></body></html>