Delegation sugar

I would like to discuss the possibility of adding a quality-of-life improvement (sugar) to give Swift more elegant ways to declare delegate protocols and conformances.

I don't know the what the best form of this would be yet, so would like to get some brainstorming going.

Let me start with an initial pitch in the form of a new, special kind of protocol: a delegation, which must be declared nested inside a class, along with a new "delegating" vertical operator |:

class Foo {
    let isCool: Bool 

    let myDelegate: any MyDelegate
    |
    delegation MyDelegate {
        func didSomething(with baz: Baz)
    }
}

class Bar {
    delegator let foo: Foo
    |
    delegated MyDelegate {
        func didSomething(with baz: Baz) {
            if foo.isCool { print("yay") }
        }
    }
}

Note: delegator vars are weak by default and conforming types must be classes (in this example). I'm not sure if we could extend such syntax to structs but I'm confident it could work with classes, so lets start there.

Benefits:

This would help avoid a lot of repetitive boilerplate like we see in many places in UIKit, e.g. UIAdaptivePresentationControllerDelegate:

protocol UIAdaptivePresentationControllerDelegate {
    func presentationController(
        _ controller: UIPresentationController,
        viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle
    ) -> UIViewController?

    func presentationController(
        _ presentationController: UIPresentationController,
        willPresentWithAdaptiveStyle style: UIModalPresentationStyle,
        transitionCoordinator: UIViewControllerTransitionCoordinator?
    )

    func presentationController(
        _ presentationController: UIPresentationController,
        willPresentWithAdaptiveStyle style: UIModalPresentationStyle,
        transitionCoordinator: UIViewControllerTransitionCoordinator?
    )

    func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController)

    func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool
}

Instead this would become:

class UIPresentationController {
    ...
    var adaptiveDelegate: AdaptiveDelegate
    |
    delegation AdaptiveDelegate {
        func viewController(for adaptivePresentationStyle: UIModalPresentationStyle)
        func willPresent(with adaptiveStyle: UIModalPresentationStyle,    transitionCoordinator: UIViewControllerTransitionCoordinator?)
        func didAttemptToDismiss()
        func shouldDismiss() -> Bool
    }   
}

Don't you think that's much more readable?

Please comment with your opinions also. Thanks!

Why would you need to write a delegate though? Because closures don't have argument labels?

How would you replace UIAdaptivePresentationControllerDelegate with closures?

Objective-C doesn't have generics so every one of its delegate methods could be syntactically replaced by a closure.

But as I said, I think this is about writing protocols, not adapting existing ones? I don't think anybody is going to put in any more Swift 3.0-style effort into making Objective-C more usable in Swift. And I don't think the delegate pattern is very useful outside of a closure/block-less object-oriented language.

Delegate is not necessarily weak by definition. I think I have seen some delegates that maintain a strong reference, such as I believe URLSessionDelegate in URLSession.

Some delegates may draw connections between delegated objects hence I don't quite understand the proposal which removes the subject out of equation.

If all you want is to implement a block based delegate, then perhaps you could make a wrapper:

final class BlockDelegate: DelegateProtocol {
  private let _didSomething: ((/* Object */) -> Void)?
  // rest of closures

  init(didSomething: (() -> Void)? = nil, /* ...rest of delegate methods */) {
       _didSomething = didSomething
  }

  func objectDidSomething(_ object: Object) {
       _didSomething?(/* object */)
  }

  // rest of delegate methods
}