“严重错误:数组无法从Objective-C桥接” —为什么还要尝试Swift,Swift?


92

我已经声明了Swift协议:

protocol Option {
    var name: String { get }
}

我声明了该协议的多种实现-一些类,一些枚举。

我有一个视图控制器,其属性声明为:

var options: [Option] = []

当我尝试将此属性设置为Option在另一个VC 中实现协议的对象数组prepareForSegue时,出现运行时错误:

fatal error: array cannot be bridged from Objective-C

为什么不起作用?编译器具有所需的所有信息,而我根本不了解Objective-C与它有什么关系-我的项目仅包含Swift文件,并且这些数组不会进出任何框架方法,必须将它们桥接到NSArray


6
您是否尝试过使用@objc协议?stackoverflow.com/a/28029568/377369
法比奥·波洛尼

1
如果任何协议实现都是枚举,那将不起作用:“非类类型'Foo'无法符合类协议'Option'”
Robert Atkins 2015年

为什么它必须是类协议?我没有将其传递给Obj-C框架或其他任何需要将Swift Array桥接到NSArray的东西。
罗伯特·阿特金斯

Swift和Objective-C一起工作的方式对我来说仍然是个秘密。我只需要“接受”很多“工作”或“不工作”的东西。
法比奥·波洛尼

9
为什么这个选票这么多?在我看来,这是一个公平而明确的问题。
2015年

Answers:


83

我找到了解决方案。相当…… 不令人满意,但是有效。我在目标视图控制器上设置数组的位置:

destinationViewController.options = options.map({$0 as Option})

你不能转换整个数组吗?options as [Option]
Kostiantyn Koval

不。尝试过(Xcode 6.3.1(6D1002)),不起作用。无论如何,我都不需要强制转换它,编译器知道我正在传递实现Option的事物数组。
罗伯特·阿特金斯

2
“实现Option的事物数组”嗯,但这与Option Array不同,这是您所需要的。看我的答案。
马特2015年

1
这行得通,是的,这是非常令人不满意的……不需要。Swift应该能够处理htis。
奥斯卡·戈麦斯

我同意...它的工作方式是这样,但这是一个非常令人不满意的代码
Michael

22

编译器知道我正在传递实现Option的事物数组

您在那儿打了一个非常有说服力的话,这表明了问题的根源。“实现选项的事物数组”不是选项的数组。

问题options出在创建它的位置(在中prepareForSegue)的背面类型。您没有显示该代码,但我敢打赌,此时您无法转换/键入它。这就是分配失败的原因。options可能实际上是采用Option的一系列事情,但这还不够;它必须作为Option数组输入

因此,回到中prepareForSegue,形成您的options样子:

let options : [Option] = // ... whatever ...

现在,您将可以直接将其分配给destinationViewController.options

这是一个快速测试用例(在操场上;我讨厌操场,但它们可以使用):

protocol Option {
    var name : String {get}
}

class ViewController : UIViewController {
    var options : [Option] = []
}

enum Thing : Option {
    var name : String {
        get {
            return "hi"
        }
    }
    case Thing
}

let vc = ViewController()
let options : [Option] = [Thing.Thing]
vc.options = options // no problem

(我还在带有实际的实际应用中对其进行了测试prepareForSegue,并且效果很好。)


1
我认为这是极端的,因为编译器在运行时确实知道Thing是一个选项。而且在任何情况下,正如下面我对自己答案的评论所指出的那样,无论是强制转换(viewController.options = things as [Option])还是创建[Option]按您在此处建议的方式显式键入的temp变量,实际上都没有作用。在这两种情况下,我都会遇到运行时错误。
罗伯特·阿特金斯

然后,您必须解释为什么它对我有用。您尚未说明的其他事情正在发生。如果您不透露更多代码,我只需要怀疑您是否在阻止一些重要的事情。
马特2015年

也许。但是我仍然对它与Objective-C的关系一无所知(相对于原始的运行时错误)。我没有做任何(我可以看到的)应将桥接强制转换为NSArray。
罗伯特·阿特金斯

2
这样看。我已经向您展示了有效的代码。您还没有显示我的代码,工作-我无法从给出的数据重现您的问题。帮我重现它。
马特2015年

1
@ CristiBăluță这就是您需要声明“此问题仍未解决”之前要查找的内容
matt

16

我遇到了同样的问题,并用标记了我的协议@objc,将其修复,在您的情况下,它看起来像这样

@objc protocol Option {
    var name: String { get }
}

得到了答案的解决方案


1
就像在原始问题的评论中一样,如果该协议的实现者是Swift Enums,则此方法将无效。就我而言,它们是。
罗伯特·阿特金斯

错字obcj应该是objc
Alan Scarpa

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.