无法在 Swift 4.2 中将 '[UITableViewCell.Type]' 类型的值转换为'[_.Type]'



好吧,今天我将Xcode更新到10.0版本后,我的代码中遇到了以下错误。

// error: Cannot convert value of type '[UITableViewCell.Type]' to expected argument type
// '[_.Type]'  
table.registerCells(cells: [MainMenuTableViewCell.self,
RescueServicesTableViewCell.self])

这是registerCells函数:

func registerCells<T> (cells : [T.Type]) where T: UITableViewCell  {
for cell in cells  {
let nib = UINib(nibName: String(describing: cell), bundle: nil)
register(nib, forCellReuseIdentifier: String(describing: cell))
}
}

一开始我认为这可能是快速重新版本控制的问题,所以我从 swift 3 转换为 swift 4,经过 2 个小时花时间修复语法,错误仍然存在,直到我做了魔术。

let cellItems = [MainMenuTableViewCell.self,
RescueServicesTableViewCell.self]
table.registerCells(cells:cellItems)

此解决方案有效,错误消失。现在我的问题是为什么我收到此错误是这个 Xcode 问题还是我做错了什么?

这是一个有趣的错误(SR-8825(,其中编译器似乎无法在成员访问中对隐式解包的可选(IUO(声明执行类型连接(推断类型集合的公共超类型的过程((大概在您的情况下table是IUO@IBOutlet(。

一个最小的例子是:

class C {}
class D : C {}
class E : C {}
struct X {
func foo<T>(_: [T.Type]) where T : C {}
}
var x: X!
// error: Cannot convert value of type '[C.Type]' to expected argument type '[_.Type]'
x.foo([D.self, E.self]) 

在执行可选链接(即x?.foo(或强制解包(即x!.foo(以执行成员访问时,使x成为非可选或强可选(即X?(允许代码编译。


您可以使用一些解决方法,首先是显式指定数组类型,使编译器不必推断类型连接:

x.foo([D.self, E.self] as [C.Type])

在您的情况下,这转化为:

table.registerCells(cells: 
[MainMenuTableViewCell.self, RescueServicesTableViewCell.self] as [UITableViewCell.Type]
)

第二种解决方法是使用非可选基础。在您的情况下,您可以在执行成员访问之前强制将 IUO 解包为局部变量:

// this is just explicitly doing what the compiler would have otherwise done implicitly.
let table = self.table!
table.registerCells(cells: [MainMenuTableViewCell.self, RescueServicesTableViewCell.self])

第三种解决方法是,正如您已经发现的那样,将数组分离到它自己的表达式中 - 这允许编译器自行执行类型连接:

let cellItems = [MainMenuTableViewCell.self, RescueServicesTableViewCell.self]
table.registerCells(cells: cellItems)

尽管在您的情况下,我会采用的解决方案是使registerCells(cells:)非通用的,因为您似乎没有使用通用占位符T来表示任何有用的东西:

extension UITableView {
func registerCells(_ cells: [UITableViewCell.Type]) {
for cell in cells  {
let nib = UINib(nibName: String(describing: cell), bundle: nil)
register(nib, forCellReuseIdentifier: String(describing: cell))
}
}
}

您现在可以这样调用:

table.registerCells([MainMenuTableViewCell.self, RescueServicesTableViewCell.self])
tableView.dequeueReusableCell(withIdentifier: String(describing: YoursCell.self), for: indexPath)

相关内容

  • 没有找到相关文章

最新更新