如何使用RxSwift和RxSwiftDataSources将表视图与表示不同数据类型的多个部分绑定?

时间:2016-11-06 23:41:08

标签: ios swift rx-swift rxdatasources

我正在尝试使用RxSwift创建包含多个部分的表视图。每个部分显示代表不同类型的数据。

我找到了RxSwiftDataSources库并从他们的文档中实现了这个示例。

以下是对该示例实施方式的快速了解:

定义了自定义数据类型CustomData

struct CustomData {
  var anInt: Int
  var aString: String
  var aCGPoint: CGPoint
}

然后,添加了该部分的表示(请注意,此处已实现SectionModelType):

struct SectionOfCustomData {
  var header: String    
  var items: [Item]
}
extension SectionOfCustomData: SectionModelType {
  typealias Item = CustomData

   init(original: SectionOfCustomData, items: [Item]) {
    self = original
    self.items = items
  } 
}

最后,创建一些示例数据并将其绑定到表视图:

let sections: [SectionOfCustomData] = [
  SectionOfCustomData(header: "First section", items: [CustomData(anInt: 0, aString: "zero", aCGPoint: CGPoint.zero), CustomData(anInt: 1, aString: "one", aCGPoint: CGPoint(x: 1, y: 1)) ]),
  SectionOfCustomData(header: "Second section", items: [CustomData(anInt: 2, aString: "two", aCGPoint: CGPoint(x: 2, y: 2)), CustomData(anInt: 3, aString: "three", aCGPoint: CGPoint(x: 3, y: 3)) ])
]

我现在想要修改示例,只想在第二部分中显示String而不是CustomData的实例,所以有点像这样:

let sections = [
  SectionOfCustomData(header: "First section", items: [CustomData(anInt: 0, aString: "zero", aCGPoint: CGPoint.zero), CustomData(anInt: 1, aString: "one", aCGPoint: CGPoint(x: 1, y: 1)) ]),
  SectionOfString(header: "Second section", items: ["a", "b", "c"])
]

这显然无法编译,因为sections现在包含不同类型SectionOfCustomDataSectionOfString的元素。我试图通过尝试将部分声明为[SectionModelType]来解决这个问题,但这不起作用,编译器抱怨:

协议“SectionModelType”只能用作通用约束,因为它具有自我或相关类型要求

1 个答案:

答案 0 :(得分:8)

您可以使用枚举来包装不同类型。

使用enum,SectionOfCustomData定义应如下所示:

some_class.py

configureCell看起来像这样:

enum SectionOfCustomData: SectionModelType {

  typealias Item = Row

  case customDataSection(header: String, items: [Row])
  case stringSection(header: String, items: [Row])

  enum Row {
    case customData(customData: CustomData) // wrapping CustomData to Row type
    case string(string: String)             // wrapping String to Row type
  }

  // followings are not directly related to this topic, but represents how to conform to SectionModelType
  var items: [Row] {
    switch self {
    case .customDataSection(_, let items):
      return items

    case .stringSection(_, let items):
      return items
    }
  }

  public init(original: SectionOfCustomData, items: [Row]) {
    switch self {
    case .customDataSection(let header, _):
      self = .customDataSection(header: header, items: items)

    case .stringSection(let header, _):
      self = .stringSection(header: header, items: items)
    }
  }
}