swift - is it possible to create a keypath to a method?

4.9k views Asked by At

Is it possible to create a keypath referencing a method? all examples are paths to variables.

I'm trying this:

class MyClass {
    init() {
        let myKeypath = \MyClass.handleMainAction
        ...
    }
    func handleMainAction() {...}
}

but it does not compile saying Key path cannot refer to instance method 'handleMainAction()

2

There are 2 answers

0
David S. On BEST ANSWER

KeyPaths are for properties. However, you can do effectively the same thing. Because functions are first class types in swift, you can create a reference to handleMainAction and pass it around:

//: Playground - noun: a place where people can play

import UIKit
import XCTest
import PlaygroundSupport

class MyClass {
    var bar = 0

    private func handleMainAction() -> Int {
        bar = bar + 1
        return bar
    }

    func getMyMainAction() -> ()->Int {
        return self.handleMainAction
    }
}

class AnotherClass {
    func runSomeoneElsesBarFunc(passedFunction:() -> Int) {
        let result = passedFunction()
        print("What I got was \(result)")
    }
}


let myInst = MyClass()
let anotherInst = AnotherClass()
let barFunc = myInst.getMyMainAction()

anotherInst.runSomeoneElsesBarFunc(passedFunction: barFunc)
anotherInst.runSomeoneElsesBarFunc(passedFunction: barFunc)
anotherInst.runSomeoneElsesBarFunc(passedFunction: barFunc)

This will work fine, and you can pass "barFunc" to any other class or method and it can be used.

1
Kelvin On

You can use MyClass.handleMainAction as an indirect reference. It gives you a block that take the class instance as the input parameter, and returns corresponding instance method.

let ref = MyClass.handleMainAction  //a block that returns the instance method
let myInstance = MyClass()
let instanceMethod = ref(myInstance)
instanceMethod()                    //invoke the instance method

The point is you can pass around / store the method reference just like what you did with a key path. You just need to supply the actual instance when you need to invoke the method.