The problem is that you are trying to access the instance methods testStaticTable and testEditableTable in the instance property initializer before self is fully initialized. Therefore, the compiler cannot partially apply these methods using self as an implicit parameter, but instead can offer you curry versions - like (MasterDispatchController) -> () -> () instead.
Then it may be tempting to mark the dispatchItems property as lazy , so that the property initializer starts when the property is first accessed, when self fully initialized.
class MasterDispatchController : UITableViewController { lazy private(set) var dispatchItems: [DispatchItem] = [ DispatchItem(description: "Static Table", f: self.testStaticTable), DispatchItem(description: "Editable Table", f: self.testEditableTable) ]
(Note that I renamed your structure according to Swift naming conventions)
Now this compiles, since now you can refer to partially applicable versions of methods (for example, type () -> Void ) and can call them like:
dispatchItems[indexPath.row].f()
However, you now have a hold loop, because you keep the closures on self , which grab self strongly. This is due to the fact that when using self.someInstanceMethod as a value, a partially closed close is allowed, which strongly fixes self .
One solution to this that you have come close to is to work with cardinal versions of methods that do not fix self strongly, but should instead be used with this instance to work on.
struct DispatchItem<Target> { let description: String let f: (Target) -> () -> Void init(description: String, f: @escaping (Target) -> () -> Void) { self.description = description self.f = f } } class MasterDispatchController : UITableViewController { let dispatchItems = [ DispatchItem(description: "Static Table", f: testStaticTable), DispatchItem(description: "Editable Table", f: testEditableTable) ] override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { dispatchItems[indexPath.row].f(self)() } func testEditableTable() {} func testStaticTable() {} }
Now these functions take the given instance of MasterDispatchController as a parameter and return the correct instance method to call this instance. So you need to apply them first with self , saying f(self) to call the instance method to call, and then call the resulting function with () .
Although it may be inconvenient to constantly apply these functions with self (or you may not even have access to self ). A more general solution would be to save self as a weak property on the DispatchItem along with the curry function - then you can apply it by request:
struct DispatchItem<Target : AnyObject> { let description: String private let _action: (Target) -> () -> Void weak var target: Target? init(description: String, target: Target, action: @escaping (Target) -> () -> Void) { self.description = description self._action = action } func action() {
This ensures that you do not have hold cycles, since DispatchItem does not have a strong reference to self .
Of course, you can use unowned self references, such as shown in this Q & A. However, you should only do this if you can guarantee that your DispatchItem instances do not expect self (you would like to make the dispatchItems a private property for one).