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

Swift error: Cannot convert value of type '() throws -> ()' to specified type 'Bool'


I have a function in Objective C that returns a BOOL and has a single errorOut parameter. The swift bridge converts the errorOut parameter into a throws as expected but it also stops the BOOL being returned.

I can see that usually the BOOL is returned to indicate success/error but in this case the bool is actually wanted. What changes would I need to make to make sure the bool gets returned?

Objective C function signature

- (BOOL)hasAnyData:(NSError *__autoreleasing *)errorOut;

Solution

  • Thanks to @MartinR for linking to a similar question where I found this trick:

    Changing the Objective C function declaration to

    - (BOOL)hasAnyData:(NSError *__autoreleasing *)errorOut __attribute__((swift_error(nonnull_error)));
    

    And then calling it from Swift like

    let hasAnyData: Bool = try self.repo.hasAnyThings()
    

    Does exactly what I wanted!

    The swift_error attribute is documented here: https://github.com/apple/swift-clang/blob/383859a9c4b964af3d127b5cc8abd0a8f11dd164/include/clang/Basic/AttrDocs.td#L1800-L1819


    Original answer - doesn't fully solve the problem but may be useful to someone else looking at this question as it is useful in a similar situation.

    I finally found this in the Swift docs:

    Use the NS_SWIFT_NOTHROW macro on an Objective-C method declaration that produces an NSError to prevent it from being imported by Swift as a method that throws.

    I have now added a NS_SWIFT_NOTHROW annotation to my Objective C function declaration like

    - (BOOL)hasAnyData:(NSError *__autoreleasing *)errorOut NS_SWIFT_NOTHROW;
    

    And am having to pass in the NSError pointer from Swift

    var error: NSError?
    let hasAnyData = self.repo.hasAnyData(&error)
    

    This isn't the nicest because I can no longer handle the error in a swifty way (using do, try catch and instead have to use the NSError) but it's the best I could find.