我将通用类存储在数组中时遇到问题。我应该如何格式化我的数组的类型,同时保持对原始类型的引用(我知道我可以做var myClasses: [Any] = []
但是从我的数组中检索变量时没有用处:(
示例如下:
import UIKit
protocol Reusable { }
extension UITableViewCell: Reusable { }
extension UICollectionViewCell: Reusable { }
class SomeClass<T> where T: Reusable {
init() { }
}
var myClasses: [SomeClass<Reusable>] = []
myClasses.append(SomeClass<UITableViewCell>())
myClasses.append(SomeClass<UICollectionViewCell>())
myClasses.append(SomeClass<UITableViewCell>())
myClasses.append(SomeClass<UICollectionViewCell>())
编辑: 为了澄清,我使用了集合和表格单元格作为示例,我实际上并没有计划将它们存储在一起:)< / em>的
编辑2 var myClasses: [SomeClass<Reusable>] = []
生成错误:using 'Reusable' as a concrete type conforming to protocol 'Reusable' is not supported
编辑3 var myClasses: [SomeClass<AnyObject>] = []
生成错误:type 'AnyObject' does not conform to protocol 'Reusable'
答案 0 :(得分:1)
我认为您可以创建某种可以接受和检索对象的Holder
类:
class Holder {
lazy var classes: [Any] = []
func get<T>(_ type: T.Type) -> [T]? {
return classes.filter({ $0 is T }) as? [T]
}
}
主要部分:
let holder = Holder()
holder.classes.append(SomeClass<UITableViewCell>())
if let someTableViewCells = holder.get(SomeClass<UITableViewCell>.self)?.first {
// or filter out again to get specific SomeClass of UITableViewCell
print(someTableViewCells)
}
或没有持有人类:
var classes: [Any] = []
classes.append(SomeClass<UITableViewCell>())
if let someTableViewCell = classes.filter({ $0 is SomeClass<UITableViewCell> }).first as? SomeClass<UITableViewCell> {
print(someTableViewCell)
}
答案 1 :(得分:1)
我的建议是为您的SomeClass通用添加父协议SomeClass Container
。然后在SomeClass中放入一个SomeClass对象数组。
protocol Reusable { func cakePlease() }
extension UITableViewCell: Reusable {
func cakePlease() { }
}
extension UICollectionViewCell: Reusable {
func cakePlease() { }
}
protocol SomeClassContainer {
func teaPlease()
func afternoonPlease()
}
class SomeClass<T: Reusable>: SomeClassContainer {
var item: T?
init() { }
func teaPlease() { }
func afternoonPlease() {
teaPlease()
item?.cakePlease()
}
}
var myClasses = [SomeClassContainer]()
myClasses.append(SomeClass<UITableViewCell>())
myClasses.append(SomeClass<UICollectionViewCell>())
myClasses.append(SomeClass<UITableViewCell>())
myClasses.append(SomeClass<UICollectionViewCell>())
myClasses[0].teaPlease()
if let item = (myClasses[0] as? SomeClass<UITableViewCell>)?.item {
item.cakePlease()
}
for myClass in myClasses {
if let tableCell = (myClass as? SomeClass<UITableViewCell>)?.item {
tableCell.cakePlease()
} else if let collectionCell = (myClass as SomeClass<UICollectionViewCell>)?.item {
collectionCell.cakePlease()
}
}
myClasses.forEach({ $0.afternoonPlease() })
答案 2 :(得分:1)
你应该在你的情况下使用AnyObject数组。因为你知道swift是强类型语言,例如
SomeClass<UITableViewCell>
和
SomeClass<UICollectionViewCell>
是不同类型的对象。例如Array&lt; Int&gt;和数组&lt;字符串&gt;,它们都是数组,但它仍然是不同类型的对象。所以在这种情况下你必须使用声明:
var myClasses: [AnyObject] = []
并检查对象的类型,或在每次需要时对它们进行类型转换。
if (myClasses[0] is SomeClass<UICollectionViewCell>) { do something }
或
if let cell = myClasses[0] as? SomeClass<UICollectionViewCell> { do something }
答案 3 :(得分:0)
一般来说,键入阵列的方式是尽可能具体,同时仍覆盖所有基础。
我的意思是,例如存储UIViewController
个对象的数组,即使每个对象实际上都是不同的类型。你不会在这里使用Any
,因为你真的不需要那么一般。
在您的情况下,为什么不使用Reusable
?因为无论如何你的所有通用类都符合它,它仍然是你可以去的一般,同时仍然保持方便。