Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.7k views
in Technique[技术] by (71.8m points)

objective c - NS_REFINED_FOR_SWIFT and return value

I'm new with Swift and I begin exploring some feature for bridging with Objective-C.

Currently I have a method with NSError reference which is:

- (BOOL) verifyPersonalizationWithError:(NSError **) error NS_REFINED_FOR_SWIFT;

Now I can access the method in Swift for some refinements, but the return value is lost. The generated method for Swift is:

open func __verifyPersonalization() throws

The error is correctly handled with the do catch but the return value seems to be lost.

Any missing thing for my NS_REFINED_FOR_SWIFT macro?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is unrelated to the NS_REFINED_FOR_SWIFT macro. The Objective-C method

 - (BOOL) verifyPersonalizationWithError:(NSError **) error;

is imported to Swift as

open func verifyPersonalization() throws

and the only effect of the NS_REFINED_FOR_SWIFT macro is to prepend underscores to the Swift method name

open func __verifyPersonalization() throws

which allows to provide a refined Swift interface in an extension, while keeping the original implementation available to be called from the refined interface (see "Refining Objective-C Declarations" in Swift and Objective-C in the Same Project).

The Swift importer assumes that the boolean return value of the Objective-C method indicates success or failure, which is the common Cocoa pattern 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.

A typical usage in Objective-C is

NSError *error;
if ([self verifyPersonalizationWithError:&error]) {
    NSLog(@"success");
} else {
    NSLog(@"failed: %@", error.localizedDescription);
}

The Swift method throws an error on failure, so there is no need for a boolean return value:

do {
    try verifyPersonalization()
    print("success")
} catch {
    print("failed:", error.localizedDescription)
}

If the Objective-C method really indicates failure by leaving a non-null error in the error parameter (instead of returning false, which is the usual Cocoa pattern) then you can indicate that by adding a attribute:

- (BOOL) verifyPersonalizationWithError:(NSError **) error
    __attribute__((swift_error(nonnull_error)));

which is imported to Swift as

open func verifyPersonalization() throws -> Bool

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...