提问人:HangarRash 提问时间:11/4/2023 更新时间:11/4/2023 访问量:48
无法将符合协议的 Swift 类的实例分配给需要该协议的 Objective-C 属性
Can't assign instance of a Swift class conforming to a protocol to an Objective-C property expecting that protocol
问:
我正在尝试在一个主要是 Objective-C 的项目中使用 Swift 类。这与 一起使用有关。UIContentConfiguration
UITableViewCell
这是我的 Swift 代码:
@objc class MyCellConfiguration: NSObject, UIContentConfiguration {
let label: String
@objc init(label: String) {
self.label = label
}
func makeContentView() -> UIView & UIContentView {
return MyCellContent(self)
}
func updated(for state: UIConfigurationState) -> Self {
return self
}
}
class MyCellContent: UIView, UIContentView {
// Implementation of this class is not relevant to the question
}
当我尝试在某些 Objective-C 代码中设置单元格时,我收到编译器警告。如果我忽略该警告,则当到达代码时,应用程序将在运行时挂起。
下面是 Objective-C 代码:
#import "MyApp-Swift.h" // The bridging header is being imported
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:key forIndexPath:indexPath];
MyCellConfiguration *config = [[MyCellConfiguration alloc] initWithLabel:@"Some Label"];
cell.contentConfiguration = config; // warning here
我收到的编译器警告是:
从不兼容的类型“MyCellConfiguration *__strong”分配给“id<UIContentConfiguration> _Nullable”
为什么编译器无法识别出符合 Objective-C 代码中的协议?MyCellConfiguration
UIContentConfiguration
Swift 代码可以很好地识别一致性。例如,以下代码编译时没有问题:
let cell = UITableViewCell(style: .default, reuseIdentifier: "foo")
cell.contentConfiguration = MyCellConfiguration(label: "foo")
我在 macOS 13.6.1 上使用 Xcode 15.0。
答:
一些观察:
UIContentConfiguration
的文档页没有可以使用“语言:Swift”选择器选择的 Objective-C 版本。Objective-C 版本在这里。UIContentConfiguration
不会像其他 Objective-C 协议那样继承,当它们被导入 Swift 时。NSObjectProtocol
- Swift 版本有一个返回交集类型的方法,该类型不能在 Objective-C 中表示。(Objective-C 版本返回
UIContentConfiguration
makeContentView
__kindof UIView<UIContentView> *
)
这些都表明,在 Swift 中,协议与它的 Objective-C 版本完全不同。仅仅在 Swift 中遵循它并不意味着你在 Objective-C 中遵循它。UIContentConfiguration
您还可以在其他相关类型(如 和)中看到类似的模式。UIContentView
UIConfigurationState
事实上,尝试在 Swift 中设置一个实例,看看 Objective-C 这边会发生什么。尝试在 Objective-C 中打印出来。输出不是 !contentConfiguration
MyCellConfiguration
[cell.contentConfiguration class]
MyCellConfiguration
总而言之,你必须在 Objective-C 中重新实现 Objective-C 版本,或者你可以在 Swift 中添加一个这样的方法:UIContentConfiguration
@objc
func addToCell(_ cell: UITableViewCell) {
cell.contentConfiguration = self
}
UITableViewCell *cell = ...;
MyCellConfiguration *config = [[MyCellConfiguration alloc] initWithLabel:@"Some Label"];
[config addToCell:cell];
评论
UIContentConfiguration
NSObjectProtocol
MyCellConfiguration
评论