Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/120.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 数组中的Swift通用协议类类型_Ios_Swift_Swift Protocols - Fatal编程技术网

Ios 数组中的Swift通用协议类类型

Ios 数组中的Swift通用协议类类型,ios,swift,swift-protocols,Ios,Swift,Swift Protocols,我们已经为我们的UITableViewCell实现了一个协议,reusible,以简化UITableView的注册/出列实现 protocol Reusable: class { static var defaultIdentifier: String { get } } extension Reusable where Self: UITableViewCell { static var defaultIdentifier: String { return S

我们已经为我们的
UITableViewCell
实现了一个协议,
reusible
,以简化
UITableView
的注册/出列实现

protocol Reusable: class {
    static var defaultIdentifier: String { get }
}

extension Reusable where Self: UITableViewCell {
    static var defaultIdentifier: String {
        return String(describing: self)
    }
}

class TestTableViewCell: UITableViewCell, Reusable { }
class AnotherTestTableViewCell: UITableViewCell, Reusable { }
然后,
UITableView
有一个扩展,比如:

extension UITableView {
    func register<T: UITableViewCell & Reusable>(_: T.Type) {
        register(UINib(nibName: T.defaultIdentifier, bundle: nil), forCellReuseIdentifier: T.defaultIdentifier)
    }
}

一切都很好,但我们希望将这些类型移动到一个数组中,以便进行排序。这就是我们被困的地方,这不起作用:

let viewCells = [TestTableViewCell.self, AnotherTestTableViewCell.self]
// Without type annotation, it's [UITableViewCell.Type]
// And the error is: Instance method 'register' requires that 'UITableViewCell' conform to 'Reusable'

for viewCell in viewCells {
    tableView.register(viewCell)
}
我们还尝试:

let viewCells: [Reusable.Type] = ...
// Error: Cannot invoke 'register' with an argument list of type '(Reusable.Type)'
还包括:

let viewCells: [(UITableViewCell & Reusable).Type] = ...
// Error: Instance method 'register' requires that 'UITableViewCell' conform to 'Reusable'

有没有一种方法可以将符合协议的类类型信息存储在一个数组中以实现这一功能?

只需为
UITableViewCell
编写一个扩展,使其符合
可重用
协议,并且不将单元格强制转换为任何类型:

extension UITableViewCell: Reusable {}

另外,您还可以在iOS上检查最流行的
可重用
协议实现


祝你好运:)

协议可重用:类{
静态变量defaultIdentifier:字符串{get}
}
扩展可重用where Self:UITableViewCell{
静态变量defaultIdentifier:字符串{
返回字符串(描述:self)
}
}
类TestTableViewCell:UITableViewCell,可重用{}
扩展UITableView{
func寄存器(uUt:T.Type){
寄存器(UINib(nibName:T.defaultIdentifier,bundle:nil),强制重用标识符:T.defaultIdentifier)
}
}
让tableView:UITableView=UITableView()
寄存器(TestTableViewCell.self)
让viewCells=[TestTableViewCell.self]
//如果没有类型注释,则为[UITableViewCell.type]
//错误是:实例方法“register”要求“UITableViewCell”符合“Reusables”
对于viewCells中的viewCell{
tableView.register(viewCell)
}

此代码成功执行。

只需使用此表视图扩展方法注册单元格即可

 extension UITableView {
     func registerCell<T: UITableViewCell>(cellType: T.Type) {
        let nib = UINib(nibName: String(describing: cellType.self), bundle: nil)
        let reuseIdentifier = String(describing: cellType.self)
        self.register(nib, forCellReuseIdentifier: reuseIdentifier)
     }
} 

希望你对此感到高兴。协议中的关键字是
Self
关键字

protocol Reusable: class {
    static var defaultIdentifier: String { get }
    static func register(tableView: UITableView)
}

extension Reusable where Self: UITableViewCell {
    static var defaultIdentifier: String {
        return String(describing: self)
    }

    static func register(tableView: UITableView) {
        tableView.register(UINib(nibName: Self.defaultIdentifier, bundle: nil), forCellReuseIdentifier: Self.defaultIdentifier)
    }
}

extension UITableView {
    func register(_ reusable: Reusable.Type) {
        reusable.register(tableView: self)
    }
}

我建议您阅读以下链接:


您使用的Swift版本是什么?@Vyacheslav 4.2有什么问题?它不编译吗?我在操场上试了试,结果成功了compiles@RicoCrescenzio是的,我编辑了这个问题,因为数组中只有一种类型的类类型。它不应该编译。“但是我们想将这些类型移动到一个数组中”这样做会有困难。斯威夫特不喜欢元类型数组的概念;在Swift中,元类型并不是真正的类型。您可能更喜欢使用其他编程语言或其他方法来实现总体目标。感谢您的回答,我看不出有什么区别,是关于Swift 4.2/5的吗?更新:当只有一个类时,它会编译,但如果有更多的类,它就不会编译。更新了问题。不幸的是,它不起作用:
类型“UITableViewCell.type”的值与强制中的“UITableViewCell&reusible”不一致
而不是在注释中讨论。让我们来做一个聊天摘要:它起作用,但是我们真的不想将协议扩展到每个
UITableViewCell
@EDUsta为什么不扩展每个
UITableViewCell
以符合协议?@JeremyP公平的问题是,有些
UITableViewCell
类没有单独的nib,或者与其名称不匹配,因此,我们还没有准备好进行转换,相反,我们正在一个接一个地进行,并了解过程(哪些单元格已准备好/未准备好)。感谢您的回答,但它只是忽略了协议,这就是我们这样做的全部原因。@EDUsta听起来很棒。如果你不介意的话,请接受我的回答
 extension UITableView {
     func registerCell<T: UITableViewCell>(cellType: T.Type) {
        let nib = UINib(nibName: String(describing: cellType.self), bundle: nil)
        let reuseIdentifier = String(describing: cellType.self)
        self.register(nib, forCellReuseIdentifier: reuseIdentifier)
     }
} 
 let tableView: UITableView = UITableView()
    let cellsArray = [Test.self, Test1.self, Test2.self]
    for cell in cellsArray {
        tableView.registerCell(cellType: cell)
    }
protocol Reusable: class {
    static var defaultIdentifier: String { get }
    static func register(tableView: UITableView)
}

extension Reusable where Self: UITableViewCell {
    static var defaultIdentifier: String {
        return String(describing: self)
    }

    static func register(tableView: UITableView) {
        tableView.register(UINib(nibName: Self.defaultIdentifier, bundle: nil), forCellReuseIdentifier: Self.defaultIdentifier)
    }
}

extension UITableView {
    func register(_ reusable: Reusable.Type) {
        reusable.register(tableView: self)
    }
}

let viewCells: [Reusable.Type] = [TestTableViewCell.self, AnotherTestTableViewCell.self]

for viewCell in viewCells {
    tableView.register(viewCell)
}