Ios 从swift中的UICollectionViewDataSource继承时的泛型类

Ios 从swift中的UICollectionViewDataSource继承时的泛型类,ios,xcode,swift,generics,uicollectionview,Ios,Xcode,Swift,Generics,Uicollectionview,当我试图创建一个在swift中实现UICollectionViewDataSource的泛型类时,它会说我的类不符合协议(有时Xcode崩溃) 这是否意味着我们不能为UICollectionView创建通用数据提供程序,并且必须复制代码 以下是通用代码: // Enum protocol protocol OptionsEnumProtocol { typealias T static var allValues:[T] {get set} var description

当我试图创建一个在swift中实现UICollectionViewDataSource的泛型类时,它会说我的类不符合协议(有时Xcode崩溃)

这是否意味着我们不能为UICollectionView创建通用数据提供程序,并且必须复制代码

以下是通用代码:

// Enum protocol
protocol OptionsEnumProtocol
{
    typealias T
    static var allValues:[T] {get set}
    var description: String {get}
    func iconName() -> String
}

// enum : list of first available options
enum Options: String, OptionsEnumProtocol
{
    typealias T = Options

    case Color = "Color"
    case Image = "Image"
    case Shadow = "Shadow"

    static var allValues:[Options] = [Color, Image, Shadow]

    var description: String {
        return self.rawValue
    }

    func iconName() -> String
    {
        var returnValue = ""

        switch(self)
        {
            case .Color: returnValue = "color_icon"
            case .Image: returnValue = "image_icon"
            case .Shadow: returnValue = "shadow_icon"
        }

        return returnValue
    }
}

// class to use as the uicollectionview datasource and delegate
class OptionsDataProvider<T>: NSObject, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
{
    private let items = T.allValues

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        return items.count
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
    {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(OptionsCellReuseIdentifier, forIndexPath: indexPath) as! GenericIconLabelCell

        let item = self.items[indexPath.row]
        // Configure the cell
        cell.iconFileName = item.iconName()
        cell.labelView.text = item.description

        return cell
    }
}
这使我有义务为我拥有的每个枚举类型复制类

确切错误:


从协议继承时,必须实现所有必需的方法。Swift 2将在一定程度上改变这一点。也许您真的想从类继承。

您是对的,不可能编写泛型类。然而,我找到了一个解决办法。它不使用枚举,所以您可能觉得它不是很有用。然而,它实现了您想要的——您将获得一个集合视图数据源,它可以与提供必要数据的不同类一起使用。代码如下:

protocol OptionsProviderProtocol
{
    func allValues() -> [OptionsItem]
}

class OptionsItem:NSObject {
    let itemDescription:String
    let iconName:String

    init(iconName:String,description:String) {
        self.itemDescription = description
        self.iconName = iconName
    }
}

// class stores first available options
class Options: NSObject, OptionsProviderProtocol
{

    let color = OptionsItem(iconName: "color_icon", description: "Color")
    let image = OptionsItem(iconName: "image_icon", description: "Image")
    let shadow = OptionsItem(iconName: "shadow_icon", description: "Shadow")

    func allValues() -> [OptionsItem] {
        return [color, image, shadow]
    }
}

// class to use as the uicollectionview datasource and delegate
class OptionsDataProvider: NSObject, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
{
    private var items:[OptionsItem] = []

    convenience init(optionsProvider:OptionsProviderProtocol) {
        self.items = optionsProvider.allValues()
    }

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        return items.count
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
    {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(OptionsCellReuseIdentifier, forIndexPath: indexPath) as! GenericIconLabelCell

        let item = self.items[indexPath.row]
        // Configure the cell
        cell.iconFileName = item.iconName()
        cell.labelView.text = item.description

        return cell
    }
}
如果你有任何问题,请告诉我

当我试图从NSOperation类继承泛型类时,我遇到了类似的问题。xCode没有给我一个编译错误,因为没有涉及任何协议,相反,我的
override func main()
从未被调用:)

无论如何。。。如果你遵循托帕尔·谢尔盖先生的建议,你就能相对容易地实现你想要的

class ViewController: UIViewController {

    @IBOutlet weak var collectionView: UICollectionView?
    private var defaultDataProvider = OptionsDataProvider<Options>()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        collectionView?.delegate = defaultDataProvider
        collectionView?.dataSource = defaultDataProvider
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}


// Enum protocol
protocol OptionsEnumProtocol {
    static var allValues: [OptionsEnumProtocol] {get set}
    var description: String {get}
    func iconName() -> String
}

// enum : list of first available options
enum Options: String, OptionsEnumProtocol {
    case Color = "Color"
    case Image = "Image"
    case Shadow = "Shadow"

    static var allValues: [OptionsEnumProtocol] = [Color, Image, Shadow]

    var description: String {
        return self.rawValue
    }

    func iconName() -> String
    {
        var returnValue = ""

        switch(self)
        {
        case .Color: returnValue = "color_icon"
        case .Image: returnValue = "image_icon"
        case .Shadow: returnValue = "shadow_icon"
        }

        return returnValue
    }
}

class OptionsDataProviderWrapper: NSObject, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    // MARK: protocols' funcs

    final func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return wrapperCollectionView(collectionView, numberOfItemsInSection: section)
    }

    final func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        return wrapperCollectionView(collectionView, cellForItemAtIndexPath: indexPath)
    }

    // MARK: for override

    func wrapperCollectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 0
    }

    func wrapperCollectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        return UICollectionViewCell()
    }
}

class OptionsDataProvider<T: OptionsEnumProtocol>: OptionsDataProviderWrapper {
    private let items = T.allValues

    override func wrapperCollectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count
    }

    override func wrapperCollectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("reuseId", forIndexPath: indexPath) as! GenericIconLabelCell

        let item = self.items[indexPath.row]
        cell.labelView?.text = item.description

        return cell
    }
}

class GenericIconLabelCell: UICollectionViewCell {
    @IBOutlet weak var labelView: UILabel?
}
类ViewController:UIViewController{
@IBVAR collectionView:UICollectionView?
private var defaultDataProvider=OptionsDataProvider()
重写func viewDidLoad(){
super.viewDidLoad()
//加载视图后,通常从nib执行任何其他设置。
collectionView?.delegate=defaultDataProvider
collectionView?.dataSource=defaultDataProvider
}
重写函数didReceiveMemoryWarning(){
超级。我收到了记忆警告()
//处置所有可以重新创建的资源。
}
}
//枚举协议
协议选项枚举协议{
静态变量allValues:[OptionsEnumProtocol]{get set}
变量说明:字符串{get}
func iconName()->字符串
}
//枚举:第一个可用选项的列表
枚举选项:字符串、选项枚举协议{
case Color=“Color”
case Image=“Image”
case Shadow=“Shadow”
静态变量allValues:[选项枚举协议]=[颜色、图像、阴影]
变量说明:字符串{
返回self.rawValue
}
func iconName()->字符串
{
var returnValue=“”
开关(自)
{
大小写颜色:returnValue=“Color\u图标”
case.Image:returnValue=“Image\u图标”
case.Shadow:returnValue=“Shadow\u图标”
}
返回值
}
}
类选项DataProviderWrapper:NSObject、UICollectionViewDelegate、UICollectionViewDataSource、UICollectionViewDelegateFlowLayout{
//马克:协议的功能
最终函数collectionView(collectionView:UICollectionView,numberOfItemsInSection:Int)->Int{
返回包装器collectionView(collectionView,numberOfItemsInSection:section)
}
最终函数collectionView(collectionView:UICollectionView,cellForItemAtIndexPath indexPath:NSIndexPath)->UICollectionViewCell{
返回包装器collectionView(collectionView,cellForItemAtIndexPath:indexPath)
}
//标记:用于覆盖
func wrapperCollectionView(collectionView:UICollectionView,numberOfItemsInSection:Int)->Int{
返回0
}
func wrapperCollectionView(collectionView:UICollectionView,cellForItemAtIndexPath indexPath:NSIndexPath)->UICollectionViewCell{
返回UICollectionViewCell()
}
}
类OptionsDataProvider:OptionsDataProviderWrapper{
私有let项=T.allValues
重写func wrapperCollectionView(collectionView:UICollectionView,numberOfItemsInSection:Int)->Int{
返回项目。计数
}
重写func wrapperCollectionView(collectionView:UICollectionView,cellForItemAtIndexPath indexPath:NSIndexPath)->UICollectionViewCell{
让cell=collectionView.dequeueReusableCellWithReuseIdentifier(“reuseId”,forIndexPath:indexPath)作为!GenericConLabelCell
让item=self.items[indexPath.row]
cell.labelView?.text=item.description
返回单元
}
}
类GenericConLabelCell:UICollectionViewCell{
@IBVAR标签视图:UILabel?
}
这里的关键是创建一个非通用的、实现所有协议的
选项DataProviderWrapper
。它所做的唯一一件事是将调用重定向到另一个函数,如
func wrapperCollectionView…

现在,您可以从此
选项DataProviderWrapper
继承泛型类,并重写该包装函数


注意:您必须完全重写包装器函数,因为本机
func collectionView…
函数不会在您的泛型子类中调用,类似于我的NSOperation问题。这就是为什么我用
final

标记本机函数的原因,我已经这样做了,这不是问题所在。我没有写所有的方法来简化。当我删除它时,它不会毫无问题地编译。为什么要投反对票?我可以有一个理由吗?你能澄清一下你想要实现什么吗?我这样问是因为如果您创建一个NSObject子类,该子类采用UICollectionViewDelegate和UICollectionViewDataSource的所有方法,您将能够将其用作集合视图的委托和数据源。所以,不清楚您想要实现什么,因为我已经将它用作uicollectionview的委托和数据源。对于这一点,它是有效的。问题是我将这个“委托/数据源”类复制到了我的每种数据类型。我的意思是,我使用枚举作为数据,我必须为每个枚举创建一个类。但我只想创建一个“委托/数据源”,并将枚举类型指定为T参数。我会更新我的问题让你明白
class ViewController: UIViewController {

    @IBOutlet weak var collectionView: UICollectionView?
    private var defaultDataProvider = OptionsDataProvider<Options>()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        collectionView?.delegate = defaultDataProvider
        collectionView?.dataSource = defaultDataProvider
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}


// Enum protocol
protocol OptionsEnumProtocol {
    static var allValues: [OptionsEnumProtocol] {get set}
    var description: String {get}
    func iconName() -> String
}

// enum : list of first available options
enum Options: String, OptionsEnumProtocol {
    case Color = "Color"
    case Image = "Image"
    case Shadow = "Shadow"

    static var allValues: [OptionsEnumProtocol] = [Color, Image, Shadow]

    var description: String {
        return self.rawValue
    }

    func iconName() -> String
    {
        var returnValue = ""

        switch(self)
        {
        case .Color: returnValue = "color_icon"
        case .Image: returnValue = "image_icon"
        case .Shadow: returnValue = "shadow_icon"
        }

        return returnValue
    }
}

class OptionsDataProviderWrapper: NSObject, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    // MARK: protocols' funcs

    final func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return wrapperCollectionView(collectionView, numberOfItemsInSection: section)
    }

    final func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        return wrapperCollectionView(collectionView, cellForItemAtIndexPath: indexPath)
    }

    // MARK: for override

    func wrapperCollectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 0
    }

    func wrapperCollectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        return UICollectionViewCell()
    }
}

class OptionsDataProvider<T: OptionsEnumProtocol>: OptionsDataProviderWrapper {
    private let items = T.allValues

    override func wrapperCollectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count
    }

    override func wrapperCollectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("reuseId", forIndexPath: indexPath) as! GenericIconLabelCell

        let item = self.items[indexPath.row]
        cell.labelView?.text = item.description

        return cell
    }
}

class GenericIconLabelCell: UICollectionViewCell {
    @IBOutlet weak var labelView: UILabel?
}