简体   繁体   中英

How to write swift 3 method with throws statement and return value that can be used in Objective C?

Below Swift 3 method is translated into Objective C like:

func doSomething(param: String) throws // Swift 3

- (BOOL)doSomething:(NSString * _Nonnull)param error:(NSError * _Nullable * _Nullable)error; // Translated Objective C

Then, how can I write a method with both throws and a return type?

func doSomething(param: String) throws -> Int // Swift 3

// Error: Never translated into Objective C

I know flow should not be handled by NSError object. It just contains information about an error. And that's why there's a BOOL return type to let us know the invocation is succeeded without any problem.

Then how can I handle a method with both throws statement and return type? Is there a standard way to handle this?

Thank you in advance.

The standard way of reporting success or failure in Objective-C is to return the boolean value NO or a nil object pointer, as documented in Using and Creating Error Objects :

Important: Success or failure is indicated by the return value of the method. Although Cocoa methods that indirectly return error objects in the Cocoa error domain are guaranteed to return such objects if the method indicates failure by directly returning nil or NO, you should always check that the return value is nil or NO before attempting to do anything with the NSError object.

So you can return a instance of an object

func doSomething(param: String) throws -> NSNumber

which is translated to

- (NSNumber * _Nullable)doSomethingWithParam:(NSString * _Nonnull)param error:(NSError * _Nullable * _Nullable)error;

and returns nil if an error is thrown, or return a boolean and pass other values back by reference

func doSomething(param: String, value: UnsafeMutablePointer<Int>) throws

which is mapped to

- (BOOL)doSomethingWithParam:(NSString * _Nonnull)param value:(NSInteger * _Nonnull)value error:(NSError * _Nullable * _Nullable)error;

试试这个:

- (int) doSomething:(NString *)param error:(NSError * _Nullable *)error;

There is another way to handle this if you can modify the throwable object.

If you can put up an enum for the errors, and annotate the error enum with @objc than the automatic bridge header will convert it to NSError like mentioned here before.

For example:

@objc enum MyError:Int, Error{
    case AnError
    case AnotherError
}

And your throwing swift method:

public class MyClass:NSObject{

    public func throwAnError() throws {
        throw MyError.AnotherError
    }

    public func callMe(){
        print("Someone called!")
    }

}

Will be converted by the auto bridging process to:

SWIFT_CLASS("_TtC13ErrorHandling7MyClass")
@interface MyClass : NSObject
- (BOOL)throwAnErrorAndReturnError:(NSError * __nullable * __null_unspecified)error;
- (void)callMe;
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end

Taken from the bottom of this excellent blog post which is relevant to this question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM