<div dir="ltr">Hi John,<div><br></div><div>I see that I&#39;ve used <font face="monospace, monospace">DispatchQueue.main</font> in my example which is probably a poor choice to demonstrate the issue:</div><div><br></div><div><font face="monospace, monospace" color="#3d85c6">  class MyClass {</font></div><div><font face="monospace, monospace" color="#3d85c6">    let queue = <span class="gmail-s1" style="font-size:13px">DispatchQueue</span><span class="gmail-s2" style="font-size:13px">(label: </span><span class="gmail-s3" style="font-size:13px">&quot;MyApp.MyQueue&quot;</span><span class="gmail-s2" style="font-size:13px">)</span></font></div><div><span class="gmail-s2" style="font-size:13px"><font face="monospace, monospace" color="#3d85c6"><br></font></span></div><div><span class="gmail-s2" style="font-size:13px"><font face="monospace, monospace" color="#3d85c6">    func start() {</font></span></div><div><span class="gmail-s2"><font face="monospace, monospace" color="#3d85c6"><div>      queue.async {</div><div>        otherClass.<span style="font-size:13px">doSomethingThatTakesAWhile()</span></div></font><font face="monospace, monospace" color="#3d85c6"><div>      }</div><div><br></div><div>      ...</div></font></span></div><div><span class="gmail-s2" style="font-size:13px"><font face="monospace, monospace" color="#3d85c6"><br></font></span></div><div><span class="gmail-s2" style="font-size:13px"><font face="monospace, monospace" color="#3d85c6">      queue.async {</font></span></div><div><span style="color:rgb(61,133,198);font-family:monospace,monospace;font-size:13px">        self.doSomething()</span></div><div><span class="gmail-s2" style="font-size:13px"><font face="monospace, monospace" color="#3d85c6">      }</font></span></div><div><span class="gmail-s2" style="font-size:13px"><font face="monospace, monospace" color="#3d85c6">    }</font></span></div><div><span class="gmail-s2" style="font-size:13px"><font face="monospace, monospace" color="#3d85c6">  }</font></span></div><div><span class="gmail-s2" style="font-size:13px"><font face="monospace, monospace" color="#3d85c6"><br></font></span></div><div><span class="gmail-s2">This would create a retain cycle wouldn&#39;t it?</span></div><div><span class="gmail-s2"><br></span></div><div><span class="gmail-s2">- Yvo</span></div><div><span class="gmail-s2"><br></span></div>







<div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Aug 30, 2017 at 6:48 PM, John McCall <span dir="ltr">&lt;<a href="mailto:rjmccall@apple.com" target="_blank">rjmccall@apple.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><br><div><span class="gmail-"><blockquote type="cite"><div>On Aug 30, 2017, at 6:45 PM, Yvo van Beek via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="gmail-m_-8240078540501221380Apple-interchange-newline"><div><div dir="ltr"><div>When I&#39;m writing code I like it to be free from any distractions that aren&#39;t really relevant to the problem that I&#39;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><br></div><div>I&#39;ve created the following helper for DispatchQueues:</div><div><br></div><div> <font face="monospace, monospace"> <font color="#3d85c6">extension DispatchQueue {</font></font></div><div><font face="monospace, monospace" color="#3d85c6">    func async&lt;T: AnyObject&gt;(weak arg: T, execute: @escaping (T) -&gt; Void) {</font></div><div><font face="monospace, monospace" color="#3d85c6">      async { [weak arg] in</font></div><div><font face="monospace, monospace" color="#3d85c6">        if let argRef = arg { execute(argRef) }</font></div><div><font face="monospace, monospace" color="#3d85c6">      }</font></div><div><font face="monospace, monospace" color="#3d85c6">    }</font></div><div><font face="monospace, monospace" color="#3d85c6">  }</font></div><div><br></div><div>It allows you to do this:</div><div><br></div><div>   <font face="monospace, monospace" color="#3d85c6">DispatchQueue.main.async(<wbr>weak: self) { me in</font></div><div><font face="monospace, monospace" color="#3d85c6">    me.updateSomePartOfUI()</font></div><div><font face="monospace, monospace" color="#3d85c6">  }</font></div><div><br></div></div></div></blockquote><div><br></div></span><div>Closures handed off to dispatch queues will not cause retain cycles.</div><div><br></div><div>John.</div><br><blockquote type="cite"><div><span class="gmail-"><div dir="ltr"><div>When functions are passed as a closure, the compiler won&#39;t warn about a possible retain cycle (there is no need to prefix with self). That&#39;s why I&#39;ve also created helpers for calling instance functions:</div><div><br></div><div>    <font face="monospace, monospace" color="#3d85c6">func blockFor&lt;Target: AnyObject&gt;(_ target: Target, method: @escaping (Target) -&gt; () -&gt; Void) -&gt; () -&gt; Void {</font></div><div><font face="monospace, monospace" color="#3d85c6">    return { [weak target] in</font></div><div><font face="monospace, monospace" color="#3d85c6">      if let targetRef = target { method(targetRef)() }</font></div><div><font face="monospace, monospace" color="#3d85c6">    }</font></div><div><font face="monospace, monospace" color="#3d85c6">  }</font></div><div><font face="monospace, monospace" color="#3d85c6"><br></font></div><div><font face="monospace, monospace" color="#3d85c6">  func blockFor&lt;Target: AnyObject, Args&gt;(_ target: Target, method: @escaping (Target) -&gt; (Args) -&gt; Void, args: Args) -&gt; () -&gt; Void {</font></div><div><font face="monospace, monospace" color="#3d85c6">    return { [weak target] in</font></div><div><font face="monospace, monospace" color="#3d85c6">      if let targetRef = target { method(targetRef)(args) }</font></div><div><font face="monospace, monospace" color="#3d85c6">    }</font></div><div><font face="monospace, monospace" color="#3d85c6">  }</font></div><div><br></div><div>Calls look like this:</div><div><br></div><div> <font face="monospace, monospace" color="#3d85c6"> class MyClass {</font></div><div><font face="monospace, monospace" color="#3d85c6">    func start() {</font></div><div><font face="monospace, monospace" color="#3d85c6">      performAction(completion: blockFor(self, method: MyClass.done))</font></div><div><font face="monospace, monospace" color="#3d85c6">    }</font></div><div><font face="monospace, monospace" color="#3d85c6"><br></font></div><div><font face="monospace, monospace" color="#3d85c6">    func done() {</font></div><div><font face="monospace, monospace" color="#3d85c6">      ...</font></div><div><font face="monospace, monospace" color="#3d85c6">    }</font></div><div><font face="monospace, monospace" color="#3d85c6">  }</font></div><div><br></div><div>When you look at code samples online or when I&#39;m reviewing code of colleagues this seems a real issue. A lot of people probably aren&#39;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">self.</font> to silence the complier :(</div><div><br></div><div>I&#39;m wondering what can be done to make this easier for developers. Maybe introduce a &#39;guard&#39; keyword for closures which skips the whole closure if the instances aren&#39;t around anymore. Since guard is a new keyword in this context it shouldn&#39;t break any code?</div><div><br></div><div>   <font face="monospace, monospace" color="#3d85c6">DispatchQueue.main.async { [guard self] in</font></div><div><font face="monospace, monospace" color="#3d85c6">    self.updateSomePartOfUI()</font></div><div><font face="monospace, monospace" color="#3d85c6">  }</font></div><div><br></div><div>I don&#39;t have any ideas yet for a better way to pass functions as closures.</div><div><br></div><div>- Yvo</div></div></span>
______________________________<wbr>_________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></div></blockquote></div><br></div></blockquote></div><br></div></div></div>