我将UICollectionViewCells的工作重构为以下内容

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中。参见评论中的主题。

更新(2/17/15)

对于那些对为什么我什至首先要这样做的人感兴趣的人,您必须了解我如何使用CollectionViewControllers(CVC)。我已经抽象了一个基本的CVC来执行每个屏幕需要的通用方法。该CVC具有一个协议(protocol),该协议(protocol)期望创建CVC模型的Factory。这些模型知道如何进行自我转换,对 Action 做出响应,并且非常像 Controller 。他们胖而活跃。另一方面,我的观点都是愚蠢的。他们只知道在屏幕上四处移动东西或进入不同的显示状态。从CVC配置单元时,您最终会做这些大的switch语句,从可读性的角度来看,这些语句实际上并不能告诉您太多信息,而是期望“路由此操作”。更糟糕的是,您开始在那里配置 View 。这并不可怕,但是对我而言,通常来说,一个 View Controller 控制着它负责的 View 。尽管此VC可能是单元的父VC,但这并没有为其提供适当的访问权限以进行大量操作。现在,这使您的VC可以执行cell.changeDisplayToActiveState()之类的操作;简而言之,它现在承担着控制其子细胞的重担。这就是那里所有“胖” VC的原因。我首先选择采用VIPER模式来偏离这条道路,但是我发现它过大了-特别是对于一个新项目。我报废了它,并开始使用基本的CVC。当前,这是我的项目的工作方式:
  • 基本的CVC期望工厂,而工厂的期望CVC(从而促进单元的双向绑定(bind))
  • 该工厂为CVC 生成单元格和 header 模型
  • 这些模型中嵌入了回调,数据和配置功能。
  • 他们可以从这些回调(因此严格区分职责)中调用 View Controller 的PUBLIC函数,例如vc.changeDisplayState(...)changeToVc(...)
  • 最佳答案

    我不确定您到底要做什么,但我会尽力回答。大概您不希望为特定的CollectionViewCellModel<X>存储一堆X,因为那样回答“我如何存储它们?”会很简单:[CollectionViewCellModel<X>]。所以我猜你想要一个异构CollectionViewCellModel<T>T数组。最好的方法是给所有CollectionViewCellModel<T>一个通用协议(protocol)(或基类,但在您的情况下,它们是struct,不是那样),大致是这样的:

    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
    

    希望这会有所帮助,

    戴夫

    关于ios - 如何在Swift中向下转换/强制转换结构的泛型类型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28503963/

    10-10 19:45