> On Aug 30, 2017, at 6:45 PM, Yvo van Beek via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> 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.
> 
> I've created the following helper for DispatchQueues:
> 
>   extension DispatchQueue {
>     func async<T: AnyObject>(weak arg: T, execute: @escaping (T) -> Void) {
>       async { [weak arg] in
>         if let argRef = arg { execute(argRef) }
>       }
>     }
>   }
> 
> It allows you to do this:
> 
>    DispatchQueue.main.async(weak: self) { me in
>     me.updateSomePartOfUI()
>   }
> 

Closures handed off to dispatch queues will not cause retain cycles.

John.

> 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:
> 
>     func blockFor<Target: AnyObject>(_ target: Target, method: @escaping 
> (Target) -> () -> Void) -> () -> Void {
>     return { [weak target] in
>       if let targetRef = target { method(targetRef)() }
>     }
>   }
> 
>   func blockFor<Target: AnyObject, Args>(_ target: Target, method: @escaping 
> (Target) -> (Args) -> Void, args: Args) -> () -> Void {
>     return { [weak target] in
>       if let targetRef = target { method(targetRef)(args) }
>     }
>   }
> 
> Calls look like this:
> 
>   class MyClass {
>     func start() {
>       performAction(completion: blockFor(self, method: MyClass.done))
>     }
> 
>     func done() {
>       ...
>     }
>   }
> 
> 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 self. to silence the complier :(
> 
> 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?
> 
>    DispatchQueue.main.async { [guard self] in
>     self.updateSomePartOfUI()
>   }
> 
> I don't have any ideas yet for a better way to pass functions as closures.
> 
> - Yvo
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to