struct CollectionViewCellModel<T: UICollectionViewCell> { let reuseIdentifier: NSString let allowsSelection: Bool // Optional callbacks var onCreate: ((T) -> Void)? = nil var onSelection: ((T) -> Void)? = nil var onWillBeDisplayed: ((T) -> Void)? = nil var onDelete: ((T) -> Void)? = nil // Create cell func toCell(collectionView: UICollectionView,indexPath: NSIndexPath) -> T { let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier,forIndexPath: indexPath) as T if let onCreate = onCreate { onCreate(cell) } return cell } }
这使我更容易创建特定单元格列表(对于表格之类的东西),然后使用它们.
但是,我一直在惹恼如何存储这些对象.我不能将它们转发到CollectionViewCellModel< UICollectionViewCell>因此无法存储[CollectionViewCellModel< UICollectionViewCell>的列表
我认为Swift支持向下转换,但显然不适用于泛型类型?
let cell = CollectionViewCellModel<A>(...) let genericCell = cell as CollectionViewCellModel<UICollectionViewCell> // ERROR: UICollectionViewCell is not identical to A let genericMaybeCell = cell as? CollectionViewCellModel<UICollectionViewCell> // ERROR: UICollectionViewCell is not identical to A
我是否必须将这些存储为Any的数组,然后每次都将它们转换为或者我只是误解某些(或两者)?
更新:我在操场上做了一些工作,以清楚地说明我的意思:
protocol IA { func name() -> String } class A:IA { func name() -> String { return "A (Base)" } } class B: A { override func name() -> String { return "B (Child of A)" } } class C: B { override func name() -> String { return "C (Child of B)" } } struct SA<T: A> { } let struct0: Any = SA<B>() // OK: yes,the struct of B is an Any! // but since B inherits from A,isn't it safe to // say that SA<B> is also of type SA<A>? let struct1: SA<A> = SA<B>() as SA<A> // NO // ERROR: 'B' is not identical to 'A' let struct1Optional: SA<A> = SA<B>() as? SA<A> // not even optionally? NO // ERROR: 'B' is not identical to 'A'
我想这不可能.也许在Swift 1.3中.请参阅评论中的主题.
更新(2015年2月17日)
对于那些对我为什么一开始就这样做感兴趣的人,你必须了解我是如何使用我的CollectionViewControllers(CVC)的.我抽象了一个基础CVC来执行每个屏幕需要的常用方法.此CVC具有一个协议,该协议需要Factory创建CVC模型.这些模型知道如何变换自己,对行动做出反应,并且非常像控制器.他们胖了&活性.另一方面,我的观点都是愚蠢的.他们所知道的只是在屏幕上移动东西或进入不同的显示状态.从CVC配置单元时,您最终会执行这些大的switch语句,这些语句实际上并没有从可读性角度告诉您“路由此”.你开始在那里配置视图会变得更糟.这并不可怕,但一般来说 – 对我来说 – 视图控制器控制着它负责的视图.虽然这个VC可能是单元的父VC,但这并没有给它适当的访问权来大量操作它.这现在让你的VC做像cell.changeDisplayToActiveState();简而言之,它现在承担着控制其子细胞的负担.这就是所有“肥胖”VC的贡献.我首先采用VIPER模式选择偏离这条道路,但我发现它过度 – 特别是对于一个新项目.我废弃它并开始使用基础CVC.这是我的项目目前的工作方式:
>一个基础CVC期望一个工厂&工厂期望CVC(从而促进细胞的双向结合)
>这家工厂生产电池和电池. THE CVC的标题模型.
>这些型号有回调和放大器数据和嵌入其中的配置功能.
>他们可以从这些回调中调用视图控制器的PUBLIC函数(因此严格分离职责),例如vc.changeDisplayState(…)或changeToVc(…)
解决方法
@H_301_32@ 我不确定你究竟是在追求什么,但我会尽力回答.据推测,你对一些特定的X存储一堆CollectionViewCellModel< X>不感兴趣,因为那时“我该如何存储它们?”的答案.很简单:[CollectionViewCellModel< X>].所以我猜你想要一个CollectionViewCellModel数组< T>对于异构T.实现这一目标的最佳方法是为所有CollectionViewCellModel< T>提供一个通用协议(或基类,但在你的情况下,它们是结构,所以不是这样),大致如下:protocol CollectionViewCellModelType { var reuseIdentifier: NSString {get} var allowsSelection: Bool {get} func toCell( collectionView: UICollectionView,indexPath: NSIndexPath ) -> UICollectionViewCell } struct CollectionViewCellModel<T: UICollectionViewCell> : CollectionViewCellModelType { let reuseIdentifier: NSString let allowsSelection: Bool // Optional callbacks var onCreate: ((T) -> Void)? = nil var onSelection: ((T) -> Void)? = nil var onWillBeDisplayed: ((T) -> Void)? = nil var onDelete: ((T) -> Void)? = nil // Create cell func toCell( collectionView: UICollectionView,indexPath: NSIndexPath ) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCellWithReuseIdentifier( reuseIdentifier,forIndexPath: indexPath) as! T if let onCreate = onCreate { onCreate(cell) } return cell } } var a: [CollectionViewCellModelType] = [] // put them in here
希望这有帮助,
戴夫