Search code examples
objective-cswiftclosuresobjective-c-swift-bridge

Calling swift closure from Objective-c


i am on macOS, objective-c. I included a Swift 5 framework and one thing i don't know is how to provide a closure.

This is the swift declaration:

var cancelledStateColorHandler: ((NSColor) -> NSColor)?

How do i pass a handler from objective-c to return an NSColor?


Solution

  • According to F*ck*ngBlockSyntax, we write a block as a var that way:

    returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
    

    var cancelledStateColorHandler: ((NSColor) -> NSColor)? would translated into swift as @property (nonatomic, copy) NSColor * _Nonnull (^ _Nullable cancelledStateColorHandler)(NSColor * _Nonnull);. To simulate it, check your Project-Swift.h file.

    I tested with

    @objc class TestClass: NSObject {
        @objc
        var cancelledStateColorHandler: ((NSColor) -> NSColor)?
    }
    

    And got:

    SWIFT_CLASS("_TtC10ProjectName9TestClass")
    @interface TestClass : NSObject
    @property (nonatomic, copy) NSColor * _Nonnull (^ _Nullable cancelledStateColorHandler)(NSColor * _Nonnull);
    - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
    @end
    

    Now, we only focus on the second part of the syntax, since the left part, is yourInstance.cancelledStateColorHandler

    ^returnType         (parameters              ) {...};
    ^NSColor * _Nonnull (NSColor * _Nonnull input) {...};
    

    So we got:

    yourInstance.cancelledStateColorHandler = ^NSColor * _Nonnull(NSColor * _Nonnull input) { 
        //Here that's sample code to show that we can use the input param, and that we need to return a value too.
        if ([input isEqual:[NSColor whiteColor]]) 
        { 
            return [NSColor redColor]; 
        } 
        else 
        { 
            return NSColor.redColor;
        }
    };