【问题标题】:Cannot call throwable Swift function from Objective-C无法从 Objective-C 调用 throwable Swift 函数
【发布时间】:2020-06-22 01:08:12
【问题描述】:

类是用 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:方法不能被标记为@objc,因为它的结果类型不能在Objective-C中表示

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

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

让 objc 调用者可以使用所有函数的正确方法是什么?

【问题讨论】:

  • 你仍然想在 Swift 中以同样的方式调用它们,对吧?
  • @Sweeper yes offcourse
  • 您介意创建这些方法的副本吗(不是它们的主体副本,只是标题)?比如你可以写另外一个方法@objc func testOptionalBoolean() -> NSNumber? { return testOptionalBoolean().map(NSNumber.init(value:)) }但是我知道有些人不喜欢有两个同名同参数的方法。
  • 返回编译器抱怨的NSNumber

标签: objective-c swift compiler-errors throwable


【解决方案1】:

错误信息很清楚:

  1. 一个可选的标量类型不能用作 ObjC 中的返回类型,因为只有对象是 nullable
  2. 为了能够将 throwing Swift 函数转换为 ObjC inout NSError 语法,就 Swift 而言,返回类型必须是 AnyObject(一个类)。

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

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

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

【讨论】:

  • 如果我想返回一个字符串或数组怎么办?没有通用的解决方案或解决方法吗?
【解决方案2】:

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

Hackingwithswift Article


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

@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
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-06
    • 2014-07-27
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 2018-11-10
    相关资源
    最近更新 更多