简体   繁体   English

Throwing 方法不能是 @objc 要求的实现,因为它返回类型为“Bool”的值

[英]Throwing method cannot be an implementation of an @objc requirement because it returns a value of type `Bool`

I have IKabaSDK.h which is a (Objective-C) protocol:我有IKabaSDK.h ,它是一个 (Objective-C) 协议:

@import Foundation;
@import MobileSdk;
    
NS_ASSUME_NONNULL_BEGIN
    
@protocol IKabaSDK <NSObject>
     
- (BOOL)isStarted:(NSError* _Nullable __autoreleasing * _Nullable)error
__attribute__((swift_error(nonnull_error)))
NS_SWIFT_NAME(isStarted());

I have a (Swift) class KabaSDKThunk where the said protocol is implemented:我有一个 (Swift) class KabaSDKThunk ,其中实现了上述协议:

class KabaSDKThunk: NSObject, IKabaSDK {
    func isStarted() throws -> Bool {
        do {
            try sdk.isStarted()
            print("thunk getIsStarted")
        } catch {
            print("thunk getIsStarted throws \(error)")
            throw error
        }
    }
    ...
}

Xcode gives me these two errors next to my implementation: Xcode 在我的实施旁边给了我这两个错误:

  • Non- @objc method isStarted() does not satisfy requirement of @objc protocol IKabaSDK@objc方法isStarted()不满足@objc协议IKabaSDK的要求
  • Throwing method cannot be an implementation of an @objc requirement because it returns a value of type Bool ; Throwing 方法不能是 @objc 要求的实现,因为它返回Bool类型的值; return Void or a type that bridges to an Objective-C class返回Void或桥接到 Objective-C class 的类型

And If I don't add Bool it complains that KabaSDKThunk does not conform to protocol IKabaSDK and suggests to add the Bool return type, so the errors are mutually exclusive.如果我不添加Bool它会抱怨KabaSDKThunk不符合协议IKabaSDK并建议添加Bool返回类型,因此错误是相互排斥的。 How do I solve the issue and why do we need Bool and throw here?我该如何解决这个问题,为什么我们需要Boolthrow在这里?

why do we need Bool and throw为什么我们需要Boolthrow

This question boils down to what you in fact want to achieve.这个问题归结为您实际上想要实现的目标。 I agree the given behaviour is inconsistent, and moreover, the Swift bridging rules were changed in the past and is likely a subject to change in future, so what you have currently broken, can turn into working sample in foreseeable future.我同意给定的行为是不一致的,此外,Swift 桥接规则在过去发生了变化,将来可能会发生变化,因此您目前所破坏的,可以在可预见的未来变成工作样本。 However for now, this error says it all:但是现在,这个错误说明了一切:

Throwing method cannot be an implementation of an @objc requirement because it returns a value of type Bool ; Throwing 方法不能是 @objc 要求的实现,因为它返回Bool类型的值; return Void or a type that bridges to an Objective-C class返回Void或桥接到 Objective-C class 的类型

In other words, if your Swift method is marked with throws keyword (and exposed to Objective-C runtime), it has to return a plain Objective-C type (not magically bridged Swift structures, like Int , Bool , Double , etc.. it has to be something subclassed from NSObject , NSProxy or other Objective-C entities) OR return nothing.换句话说,如果您的 Swift 方法标有throws关键字(并暴露给 Objective-C 运行时),它必须返回一个普通的 Objective-C 类型(不是神奇地桥接 Swift 结构,如IntBoolDouble等。它必须是NSObjectNSProxy或其他 Objective-C 实体的子类)或不返回任何内容。 Period.时期。 Take it as a rule (at least for now).把它作为一个规则(至少现在)。 ( PS This specific situation indeed looks like an LLVM bug, because the same set of requirements works perfectly fine when applied to a non-protocol Objective-C method (submitted it here , so the community has a chance to review it)) PS这种特定情况确实看起来像一个 LLVM 错误,因为相同的一组要求在应用于非协议 Objective-C 方法时工作得很好(在此处提交,因此社区有机会审查它))

Having that said, the proper workaround to this situation depends on your final goal.话虽如此,这种情况的正确解决方法取决于您的最终目标。

"Conventional" failable method “常规”失败方法

By "conventional" here I mean a contract that Cocoa/Cocoa touch programmer would usually expect.这里的“常规”是指 Cocoa/Cocoa touch 程序员通常期望的合同。 In this scenario a method with the following signature:在这种情况下,具有以下签名的方法:

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

Is commonly meant to fail wherever it returns NO value (in the world of Objective-C).通常意味着在返回NO值的任何地方失败(在 Objective-C 的世界中)。 It's uncommon for Swift to deal with indirect parameters like NSError ** so in order to keep it consistent such methods are bridged as follows: Swift 处理像NSError **这样的间接参数并不常见,所以为了保持一致,这些方法桥接如下:

func failableMethod() throws

You can read more about this convention in the About Imported Cocoa Error Parameters documentation .您可以在关于导入的 Cocoa 错误参数文档中阅读有关此约定的更多信息。

Failable method with preserved return type with swift_error(nonnull_error) attribute带有swift_error(nonnull_error)属性的保留返回类型的失败方法

If you want to preserve return type AND the failable signature, you have two options.如果您想保留返回类型和可失败签名,您有两个选择。 First is by giving the method swift_error(nonnull_error) attribute.首先是给方法swift_error(nonnull_error)属性。 However in this case, in order to comply with existing bridging rules, your method has to have a type that "bridges" to an Objective-C class, eg NSNumber * :但是在这种情况下,为了遵守现有的桥接规则,您的方法必须具有“桥接”到 Objective-C class 的类型,例如NSNumber *

- (NSNumber *)failableMethodWithError:(NSError ** _Nullable)error __attribute__((swift_error(nonnull_error)));

And here is how you implement such a method in Swift:以下是如何在 Swift 中实现这种方法:

func failableMethod() throws -> NSNumber {
    return NSNumber(booleanLiteral: false)
}

Failable method with preserved return type with swift_error(none) attribute带有swift_error(none)属性的保留返回类型的失败方法

Another option to preserve the return type is by disabling Objective-C - Swift error signature conversion at all with use of swift_error(none) attribute:保留返回类型的另一种选择是通过使用swift_error(none)属性完全禁用 Objective-C - Swift 错误签名转换:

- (BOOL)failableMethodWithError:(NSError ** _Nullable)error __attribute__((swift_error(none)));

In this scenario you can return a scalar type from the failable method, but at the same time you will have to deal with NSErrorPointer type:在这种情况下,您可以从可失败方法返回一个标量类型,但同时您将不得不处理NSErrorPointer类型:

func failableMethodWithError(_ error: NSErrorPointer) -> Bool {
    if (/*error condition */) {
        error?.pointee = NSError(domain: TDWErrorDomain, code: TDWErrorDomainErrorCode)
    }
    return true
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 抛出方法不能是@objc协议的成员,因为它返回类型'Bool'的值 - Throwing method cannot be a member of an @objc protocol because it returns a value of type 'Bool' Method cannot be marked @objc because the type of parameter 3 cannot be represented in Objective-C - @objc func 中无法识别错误类型? - Method cannot be marked @objc because the type of the parameter 3 cannot be represented in Objective-C - Error type not recognized in @objc func? 方法不能标记为@objc,因为其结果类型无法在Objective-C中表示 - Method cannot be marked @objc because its result type cannot be represented in Objective-C 方法不能是 @objc 协议的成员,因为它的结果类型不能在 Objective-C 中表示 - Method cannot be a member of an @objc protocol because its result type cannot be represented in Objective-C Swift 2.0 Method 无法标记@objc 因为参数的类型无法在Objective-C中表示 - Swift 2.0 Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C Swift 5 方法不能标记为@objc 因为参数2的类型不能在Objective-C中表示 - Swift 5 Method cannot be marked @objc because the type of the parameter 2 cannot be represented in Objective-C 无法将类型&#39;()-&gt; _&#39;的值转换为指定的类型&#39;布尔&#39; - Cannot convert value of type '() -> _' to specified type 'Bool' 无法转换类型&#39;()的值? 到指定类型布尔 - Cannot convert value of type '()?' to specified type Bool 无法将类型“布尔”的值分配给类型“ UIButton?” - Cannot assign value of type 'Bool' to type 'UIButton?' 无法将类型“()”的值转换为指定类型“Bool” - Cannot convert value of type '()' to specified type 'Bool'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM