Swift 通用协议 Class 输入数组
Swift Generic Protocol Class Type in Array
我们已经实施了一个协议,Reusable
,以简化 UITableView
register/dequeue 实施,我们的 UITableViewCell
s。
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 tableView: UITableView = UITableView()
tableView.register(TestTableViewCell.self)
tableView.register(AnotherTableViewCell.self)
一切正常,但我们想将这些类型移动到一个数组中,以便排序。这就是我们卡住的地方,这是行不通的:
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'
有没有办法将 class 类型信息与协议一致性存储在数组中以使其工作?
只需为 UITableViewCell
编写一个扩展,使其符合 Reusable
协议并且不要将单元格转换为任何类型:
extension UITableViewCell: Reusable {}
P.S。您还可以在 iOS here. 上查看最流行的 Reusable
协议实现
祝你好运:)
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 { }
extension UITableView {
func register<T: UITableViewCell & Reusable>(_: T.Type) {
register(UINib(nibName: T.defaultIdentifier, bundle: nil), forCellReuseIdentifier: T.defaultIdentifier)
}
}
let tableView: UITableView = UITableView()
tableView.register(TestTableViewCell.self)
let viewCells = [TestTableViewCell.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)
}
此代码成功执行。
只需使用这个 table 视图扩展方法来注册单元格。
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)
}
希望您对此感到满意。关键是协议中的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)
}
}
let viewCells: [Reusable.Type] = [TestTableViewCell.self, AnotherTestTableViewCell.self]
for viewCell in viewCells {
tableView.register(viewCell)
}
我建议您阅读以下链接:
我们已经实施了一个协议,Reusable
,以简化 UITableView
register/dequeue 实施,我们的 UITableViewCell
s。
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 tableView: UITableView = UITableView()
tableView.register(TestTableViewCell.self)
tableView.register(AnotherTableViewCell.self)
一切正常,但我们想将这些类型移动到一个数组中,以便排序。这就是我们卡住的地方,这是行不通的:
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'
有没有办法将 class 类型信息与协议一致性存储在数组中以使其工作?
只需为 UITableViewCell
编写一个扩展,使其符合 Reusable
协议并且不要将单元格转换为任何类型:
extension UITableViewCell: Reusable {}
P.S。您还可以在 iOS here. 上查看最流行的
Reusable
协议实现
祝你好运:)
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 { }
extension UITableView {
func register<T: UITableViewCell & Reusable>(_: T.Type) {
register(UINib(nibName: T.defaultIdentifier, bundle: nil), forCellReuseIdentifier: T.defaultIdentifier)
}
}
let tableView: UITableView = UITableView()
tableView.register(TestTableViewCell.self)
let viewCells = [TestTableViewCell.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)
}
此代码成功执行。
只需使用这个 table 视图扩展方法来注册单元格。
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)
}
希望您对此感到满意。关键是协议中的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)
}
}
let viewCells: [Reusable.Type] = [TestTableViewCell.self, AnotherTestTableViewCell.self]
for viewCell in viewCells {
tableView.register(viewCell)
}
我建议您阅读以下链接: