A shortcut for weak actions

A have a sort of coordinator class that builds several UIViewControllers and sets some closures to customize their behaviour:

func termsAndConditions() -> UIViewController {
    let vc = TermsConditionsController()
    vc.completion = { [weak self] in
        guard let `self` = self else { return }
        self.navigationVC.push(self.welcomeScreen(), animated: true)
    }
    return vc
}

func welcomeScreen() -> UIViewController {
    let vc = WelcomeScreenController()
    vc.signUpAction = { [weak self] in
        guard let `self` = self else { return }
        self.navigationVC.push(self.userProfileScreen(), animated: true)
    }
    return vc
}

How can I get rid of the repeated weak-callback code? I tried to toy with unapplied methods, a bit like this:

typealias Action = () -> Void
typealias Screen = (Self) -> () -> UIViewController

func push(_ screen: @escaping Screen, animated: Bool = true) -> Action {
    return { [weak self] in
        guard let `self` = self else { return }
        self.navigationVC.push(screen(self)(), animated: animated)
    }
}

But the unapplied method types come out a bit awkward and referring to methods in the same class requires qualifying with the current class name:

func welcomeScreen() -> UIViewController {
    let vc = WelcomeScreenController()
    vc.signUpAction = push(ThisClassName.userProfileScreen)
    return vc
}

I also tried toying with key paths (where the syntax ends up really nice, like push(\.userProfileScreen)), but then I am out of luck when the builder method needs an argument (userProfileScreen(forUser: …)).

Are there better options?

1 Like