Swift: "Cannot assign value of type 'Item!' to type 'Item!"

Swift: "Cannot assign value of type 'Item!' to type 'Item!"

我有一个混合的 Obj-C - Swift 应用程序。
我的自定义 Obj-C MapViewController 具有以下头文件,其中 Item 是用 Swift 编写的自定义 class:

@class Item;
@interface MapViewController : UIViewController
@property (nonatomic, strong) Item *item;
@end

MapViewController 的 segue 使用

通过 Item 对象 item 启动
self.performSegueWithIdentifier(kMapSegueId, sender: item)

此调用,其中 item 作为 sender 发送:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == kMapSegueId {
        let mapViewController = segue.destinationViewController as! MapViewController
        mapViewController.item = sender as! Item! // This gives the error
    }
}

但是,对 MapViewController 的 属性 item 的赋值给出了编译器错误

无法将类型 'Item!' 的值分配给类型 'Item!'

如何避免这个奇怪的错误?

删除多余的 !。您应该转换为 Item,而不是 Item!

    mapViewController.item = sender as! Item

编译器试图在这里建立太多的隐式桥接;这是一座桥太远了。尽管我打赌 .item 的类型是 Item!,但您应该忽略它并始终将其设为 Item。 Swift 2.2 中的 ! 类型在它们周围有很多复杂性(并且应该尽可能避免)与许多神奇的 ObjC 桥接相关。这就是它们在 Swift 3.

中重新设计的原因

以上是正确的,但可能不是你的问题。问题是 sender 本身是可选的。因此,您正在尝试从 AnyObject? 转换为 Item。您需要先使用 if let!.

打开 sender
    mapViewController.item = sender! as! Item

我可能会将其重写为:

if let item = sender as? Item,
    mapViewController = segue.destinationViewController as? MapViewController
    where segue.identifier == kMapSegueId {
    mapViewController.item = item
}

正如 vadianRob Napier 所建议的那样,由于 Item[= 后面的感叹号,我的代码是错误的24=].
但是,删除它确实会产生另一个编译器错误。原因如下:

当我开始将我现有的 Obj-C 项目转换为 Swift 时,我设置了桥接 header,并在那里导入了我所有的 h-files,因为我所有的classes 是在 Obj-C 中编写的。然后我开始将 class 由 class 翻译成 Swift.
我忘记删除文件的 #import 语句,这些文件已经翻译成 Swift。 所以,classes 仍然有导入语句ItemViewController

我从桥接 header 中删除这些导入语句后,编译器错误就消失了。