提问者:小点点

无法从Objective-C调用可抛出的Swift函数


类是用Swift编写的,

@objc class Test: NSObject {

    @objc func testBoolean() -> Bool {
        return true
    }

    @objc func testOptionalBoolean() -> Bool? {
        return true
    }

    @objc func testThrowableBoolean() throws -> Bool {
        return true
    }

    @objc func testThrowableOptionalBoolean() throws -> Bool? {
        return true
    }
}

在这些函数中,只有第一个函数是可编译的。

testOptionalBoolean:方法不能被标记为@Objective-C,因为它的结果类型不能在Objective-C中表示

testThrowableBoolean:抛出方法不能被标记为@Objectivc,因为它返回一个Bool类型的值;返回'Void'或桥接到Objective-C类的类型

testThrowableOptionalBoolean:方法无法标记为@objectivc,因为它的结果类型无法在Objective-C中表示

使所有函数都可用于Objec调用者的正确方法是什么?


共2个答案

匿名用户

错误消息非常清楚:

  1. 可选的标量类型不能用作ObjC中的返回类型,因为只有对象可以为空
  2. 为了能够将抛出ing Swift函数转换为ObjC inoutNSError语法,返回类型必须是AnyObject(一个类)。

例如,您可以将Bool类型替换为NSNumber

@objc func testOptionalBoolean() -> NSNumber? {
    return true // Yes, returning a Swift Bool is valid
}

但是即使使用NSNumber函数testThrowableOptionalBoolean也无法编译,因为抛出函数的设计是在成功时返回非可选的

匿名用户

SE-0230修改了try?的工作方式,使嵌套选项被展平为常规选项。这使得它的工作方式与可选链接和条件类型转换相同,这两种类型转换在早期的Swift版本中都展平了选项。

Hackingwithswift文章

您可以创建一个对象作为包装器。

@objc class Test: NSObject {

    @objc func testBoolean() -> Bool {
        return true
    }

    @objc func testOptionalBoolean() -> BooleanWrapper? {
        return BooleanWrapper(true)
    }

    @objc func testThrowableBoolean() throws -> BooleanWrapper {
        return BooleanWrapper(true)
    }
}

使用

if let wrapper = try? test.testThrowableBoolean() {
    print(wrapper.bool)
}

包装纸

@objc class BooleanWrapper: NSObject {

    let bool: Bool

    init(_ bool: Bool) {
        self.bool = bool
    }
}