Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling an optional function in Swift

Tags:

swift

optional

I'm trying to work out a way to call methods dynamically by number. Here's a simplified version of what I'm doing.

class C {

    func a() {}
    func b() {}

    let f = [0: a, 1: b]

    func call(n: Int) {
        f[n]?()
    }
}

let c = C()

c.call(0)

When I run this in a playground I get

Playground execution failed: error: <REPL>:10:13: error: could not find an overload for 'subscript' that accepts the supplied arguments
    f[n]?()
    ~~~~^~~

Yet if I run

func a() {}
func b() {}

let f = [0: a, 1: b]

f[0]?()

directly with no containing class it works as expected. What's going on?

like image 318
Michael Dorst Avatar asked Jun 10 '14 06:06

Michael Dorst


People also ask

How are optional implemented in Swift?

How are optionals implemented in Swift. We have already noted that an optional is a wrapper that can wrap an instance of a given Swift type. This is implemented using a generic enum as follows. The enum has two cases, to represent the absence and presence of a wrapped instance respectively.

How do I return optional in Swift?

Swift lets you override its safety by using the exclamation mark character: ! . If you know that an optional definitely has a value, you can force unwrap it by placing this exclamation mark after it.

What does optional mean in Swift?

Optional types or Optionals in Swift You use optionals in situations where a value may be absent. An optional represents two possibilities: Either there is a value, and you can unwrap the optional to access that value, or there isn't a value at all.


1 Answers

This is really interesting! I noticed that your first bit of code ran fine if I moved the function definitions outside of the class but kept everything else the same. From the error message I was able to conclude that when the functions are declared within the class they need to be called with an instance of the class. When you just call a() inside the class the compiler is automatically interpreting that as self.a(). However, when the function is stored in a variable (f[0], f[1], etc.) it needs to be passed an instance of class C (self) first. This works:

class C {

    func a() {println("in a")}
    func b() {println("in b")}

    let f = [0: a, 1: b]

    func call(n: Int) {
        a() // works because it's auto-translated to self.a()
        f[n]?(self)() // works because self is passed in manually
    }
}

let c = C()

c.call(0)
like image 132
Dash Avatar answered Sep 26 '22 15:09

Dash