All func pointers need a protocol now?

I'm trying to do this simple callback method:


final class MyView: UIView {
    var onSomeAction: ((String) -> Void)!
}

final class MyViewController: UIViewController {
    let myView = MyView(frame: CGRectZero)
    override func viewDidLoad() {
        super.viewDidLoad()
        myView.onSomeAction = someFunc
    }

    private func someFunc(str: String) {
    }
}


But that's going to create a retain cycle (I believe). I can't just mark the onSomeAction var as weak because that's a compile time error.


Do I really need to go to the level of defining a protocol for this just so I can mark it as a class protocol and then mark that callback to be a weak reference?


I've gotta be missing something here.

Accepted Reply

var onSomeAction_get: () -> (String -> Void)! = {nil}

myView.onSomeAction_get = {[unowned self] in self.someFunc}

Replies

var onSomeAction_get: () -> (String -> Void)! = {nil}

myView.onSomeAction_get = {[unowned self] in self.someFunc}

That doesn't really make sense. You're still capturing a strong reference in MyView. Your [unowned self] just says that the closure itself won't capture itself strongly.

Fixed. Sorry. Tired.


This is one of my use cases for mutable property accessors.

So, what's your take? This is what I've been using as a replacement for delegates, except with weak instead of unowned.

It definitely has to be weak, and I think it would work. Just feels a bit like a missing language feature. It's too easy to just assign a function to a property like this and think things are OK, only to later realize you've made a retain cycle. We should somehow be able to tell Swift that the pointer to the closure should always be weak without needing a protocol for it.

I agree.


And as for mutable accessors, here's what I use when both get and set need to be mutable:

https://github.com/Catterwaul/HemiprocneMystacea/blob/master/HemiprocneMystacea/Swift/Properties/Mutable%20Properties.swift


What I want this to look like is this:

weak var onSomeAction: (String -> Void)?
myView.onSomeAction get = {[weak self] in self?.someFunc}