0

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;
Inti
  • 3,443
  • 1
  • 29
  • 34
  • Not a duplicate of https://stackoverflow.com/questions/45565960/ns-refined-for-swift-and-return-value as although the answer leads you to the right solution the question is different. Also, definitely not a duplicate of https://stackoverflow.com/questions/35810651/swift-error-cannot-convert-of-type-to-specified-type-bool – Inti Nov 11 '17 at 11:08
  • That is what is meant by a duplicate. That he answers are the same. Not that the question is identical. – Dijkgraaf Nov 11 '17 at 18:48

1 Answers1

1

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.

Inti
  • 3,443
  • 1
  • 29
  • 34
  • 2
    `__attribute__((swift_error(nonnull_error)))` should be what you need, compare https://stackoverflow.com/a/45566261/1187415. – Martin R Nov 10 '17 at 21:50
  • That looks like exactly what I need - I'll test it and update my answer accordingly. Thanks @MartinR – Inti Nov 11 '17 at 11:01