Michael
Michael

Reputation: 33307

Anonymous inner Class in Swift

In Java I can do the following:

interface SomeCallback {
  void onDone();
}

then I can create a function like this:

void test(SomeCallback callback) {
...
}

To call this function I do:

test(new SomeCallback() {
 @Override
 void done() {
 ...
 }
});

I want to do something similar in Swift. I could create a protocol

protocol SomeCallback : class {
  func done()
}

and a function like this

func test(callback: SomeCallback) {
...
}

I am still struggling with the call of this function.

Edit: Since I use an external API which requires a delegate I cannot use a Closure.

Is it possible to create some kind of anonymous inner class like I did it in the Java example to call test()?

Upvotes: 1

Views: 1734

Answers (2)

Jesper
Jesper

Reputation: 7615

Update: If you can't use a closure/function, the direct answer is: no, there are no anonymous inner classes. However, as Mike M points out, you'll have to use a class, and this class may be nested/inner to prevent polluting the global namespace. This class may well have a closure for every method it needs to implement and just call through to those closures.


The Swift-y way of doing this as long as you just need one method is to just use a lambda/closure.

For example, see NSComparator, which is typealiased since it is used all over the place and you are meant to recognize it.

In your example, specifying a function type inline will do fine. So for example:

func test(callback: () -> Void) {
    ...
    callback()
}

// called as:
test({ in 
    ...
})

// or even (since it's the last parameter)
test { in 
    ...
}

Upvotes: 2

Mike M
Mike M

Reputation: 5132

Just to clarify the syntax because what you wrote is a little confusing.

@objc protocol SomeCallback {
    func done() -> Void
}

No need to inherit from class as you wrote. Also, don't forget the @objc even if you do not want to bridge the protocol to that language. It helps with compiler complaints later on (might be a bug at the moment)

You cannot instantiate a protocol in Swift. You can however have an internal class that inherits from NSObject (root object) and implements this.

class External: NSObject {

    class Internal : SomeCallback {
        func done() {
            // does something
        }
    }
    let int = Internal()

    func test(callback : SomeCallback) {
        // additional work
        callback.done()
    }
}

Upvotes: 0

Related Questions