> On Feb 19, 2017, at 6:45 AM, Matthew Johnson <matt...@anandabits.com> wrote: > > 1. Swift *already* acknowledges that it is far easier to create a reference > cycle through captured strong references to `self` than any other way. This > is why you have to explicitly say `self.` in escaping closures.
The reason you have to explicitly say `self` is that `self` is the only variable you can implicitly reference. That's disabled in closures, so it's on the same footing as other variables. Other than that, the only reason `self` is more likely to cause a loop is that, in common Cocoa patterns, you're more likely to be handing the closure to something owned by `self`. But that's not *necessarily* the case, it just happens to be true in many cases. > 2. There are *already* APIs which are designed to capture an object weak and > then call a method on it if it's still around when an event occurs. In fact > this has been a trend in Apple's newer APIs. Users are able to learn the > semantics of these APIs without a problem. In fact, users like the, because > they solve a real problem by ensuring that3. object lifetime is not extended > when using them. > > 3. Swift libraries don't tend to design APIs with weak callback semantics, > probably because they are currently syntactically heavy for both users and > libraries. This is true even when weak callback semantics would be > beneficial for users and help prevent leaks (which can lead to crashes and > other badly behaved apps). > > 4. There have been several ideas proposed to make weak capture easier to do > on the call side but they haven't gone anywhere. The syntactic savings > aren't that significant for callers and the burden is still on callers to get > it right. I definitely agree this is a problem, but again, that doesn't mean `self` is the issue here. I think this is mainly because (a) the pattern isn't taught, and (b) there are some minor speed bumps in current Swift (like the inability to shadow `self` in a closure parameter list). > If users actually need a strong reference there are ways to handle that. > First, if it is likely that a user might want self to be captured strong the > API might choose to not use `@selfsafe`. This doesn't work. The API designer doesn't know what's at the call site, and the user can't modify the API to suit the use. > If they *do* choose to use it the could also add an overload that does not > use it and is disambiguated using some other means (base name or argument > label). That seems like an ugly way to design APIs. > Finally, users can always add an extra closure wrapper {{ self.myMethod() }} > to bypass the API's weak callback semantics. Here, `self` is captured by the > inner closure rather than the the outer closure and the API only converts > strong `self` references in the outer closure. That wouldn't work. The outer closure captures `self` from the context, and the inner closure captures `self` from the outer closure. The outer closure's capture would still be weak. I really think this focus on `self` is counterproductive. I'm thinking we might be able to address this in a different way. Let's look at your code sample: addAction(takesInt) With the implicit `self`s made explicit, that would instead be: self.addAction( self.takesInt ) Now let's look at mine: alert.addAction(UIAlertAction(title: "Delete", style: .destructive) { _ in … viewController.performSegue(withIdentifier: "Cancel", sender: self) }) … viewController.present(alert) These have a similar pattern: The closure ends up being passed to a method on one of the variables it captures. Your example: self.addAction( ^ Closure gets passed to method on `self` self.takesInt ^ Closure captures `self` ) Mine: alert.addAction(UIAlertAction(title: "Delete", style: .destructive) { _ in ^ Closure passed to method on `alert` … viewController.performSegue(withIdentifier: "Cancel", sender: self) ^ Closure captures `viewController` }) … viewController.present(alert) ^ `alert` passed to `viewController` This seems like something the compiler—or perhaps a static analyzer?—could warn about. And it wouldn't target `self` specifically, or silently change the meaning of your code. -- Brent Royal-Gordon Architechies _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution