UICollectionviewcell的子类无法实现为泛型

时间:2019-05-09 08:17:59

标签: swift generics polymorphism uicollectionviewcell

我希望动态创建一些collectionviews。

当调用我的工厂函数时,我想将其传递给UICollectionViewCell的子类类型。我正在使用类型化泛型来完成此任务。 但是,编译器使我停下脚步,并让我质疑我对Swift中多态性的理解。

有人可以阐明这件事吗?

我的CustomCell



public class DiscoverySmallCollectionCell: UICollectionViewCell {


    public var mainView : DiscoveryNavigationCard


    public init(image: UIImage) {
        self.mainView = DiscoveryNavigationCard(largeImage: image)
        super.init(frame: CGRect.zero)
        self.translatesAutoresizingMaskIntoConstraints = false
        setup()
    }

    override public init(frame: CGRect) {
        self.mainView = DiscoveryNavigationCard()
        super.init(frame: CGRect.zero)
        self.translatesAutoresizingMaskIntoConstraints = false;
        setup()
    }

    public init() {
        self.mainView = DiscoveryNavigationCard()
        super.init(frame: CGRect.zero)
        self.translatesAutoresizingMaskIntoConstraints = false
        setup()
    }

    private func setup(){
        self.addSubview(mainView)
        pinToParent(view: mainView, parent: self)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

我的控制器: 有问题的功能签名:


    private func createColletionViewAndContainer <T>(identifier: String, cellSize: CGSize, cellType: T) where T: UICollectionViewCell {

呼叫功能:


    private func setupCollectionViews(items: [DiscoveryItem]) {

        for item in items {
            let category = item.category
            switch category {
            case "hospital", "favourites":
                self.createColletionViewAndContainer(identifier: category, cellSize: LocalLayout.smallCellSize, cellType: DiscoverySmallCollectionCell )

            default :
                self.createColletionViewAndContainer(identifier: category, cellSize: LocalLayout.largeCellSize, cellType: DiscoveryLargeCollectionCell)

            }
        }
        setup()
    }

2 个答案:

答案 0 :(得分:0)

如果要使用泛型设置可重用单元格,这是一种简单的模式:

第一

设置通用单元格,在此示例中,它仅接受一个参数,但是您可以执行任何想要的操作

class GenericCollectionViewCell<U>: UICollectionViewCell {
    var item: U!
}

第二

创建一个UIViewController来接受您的通用单元格

class GenericViewController<T: GenericCollectionViewCell<U>, U>: UIViewController, UICollectionViewDelegate {
    var items: [U] = []

    fileprivate let cellReuseIdentifier = "GenericCollectionViewCell"

    override func viewDidLoad() {
        collectionView.register(T.self, forCellWithReuseIdentifier: cellReuseIdentifier)
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellReuseIdentifier, for: indexPath) as? GenericCollectionViewCell<U> else { return UICollectionViewCell() }
        cell.item = items[indexPath.item]
        return cell
    }
}

第三

子类化您的通用单元并完成所有设置

class MySublclassedCollectionViewCell: GenericCollectionViewCell<Whatever> {
  override var item: Whatever! { // see that item becomes of type Whatever
      didSet {
        // setup your cell from here
      }
  }
}

最终

抢占GenericViewController并完成工作

class SublcassedViewController: GenericViewController<GenericCollectionViewCell, Whatever> {
  override func viewDidLoad() {
     super.viewDidLoad()

       self.items = // setup items 
  }
}

答案 1 :(得分:0)

在读了一些优秀的文章之后: IOS 12 Swift编程基础知识我发现了这个问题。与语法有关。

参数cellType必须为:T.Type,而不是:T。

正确的签名是:

  private func createColletionViewAndContainer  <T>(identifier: String, cellSize: CGSize, cellType: T.Type) where T: UICollectionViewCell {}

调用方应在cellType后面附加.self:

(signature....cellType: SomeClass.self) 

因此,如果Matt Neuburg在外面:我会接受你的回答:P

非常感谢所有做出回应的人!