I've got 2 arrays: roomsArray:[Auditorie] and groupsArray:[Group]. I appended them into roomsAndGroups:[[Any]]. The question is how to populate tableView with 2D array or with 2 arrays of different types.

struct Auditorie: Codable {
    let id: Int
    let name: String
    let building: Building
}

struct Building: Codable {
    let name: String
    let abbr: String
}

struct Group: Codable {
    let id: Int
    let name: String
}

fileprivate var roomsArray:[Auditorie] = []
fileprivate var groupsArray:[Group] = []
fileprivate var roomsAndGroups:[[Any]] = []


Array looks like this

[[PolyStudents.Group(id: 26025, name: "23254/1"), PolyStudents.Group(id: 26605, name: "43325/2"), PolyStudents.Group(id: 26615, name: "43325/3"), PolyStudents.Group(id: 27121, name: "53325/3"), PolyStudents.Group(id: 26055, name: "33254/1"), PolyStudents.Group(id: 26056, name: "33253/1"), PolyStudents.Group(id: 25976, name: "13254/1"), PolyStudents.Group(id: 26026, name: "23255/1"), PolyStudents.Group(id: 26604, name: "43325/1"), PolyStudents.Group(id: 26057, name: "33255/1")], [PolyStudents.Auditorie(id: 1579, name: "1325", building: PolyStudents.Building(name: "50 учебный корпус", abbr: "50 уч.к")), PolyStudents.Auditorie(id: 1641, name: "325", building: PolyStudents.Building(name: "11-й учебный корпус", abbr: "11 к."))]]

1 Answers

1
ajeferson On Best Solutions

I can see two ways for you to achieve that. First, as per ielyamani's comment, you can use a common protocol. Second, you can wrap your types in an enum.

Option 1

Suppose the name property is the only common among your type. So you can create a protocol like:

protocol Nameable {
  var name: String { get }
}

Then conform your types to that:

struct Auditorie: Codable, Nameable {
  let id: Int
  let name: String
  let building: Building
}

struct Building: Codable, Nameable {
  let name: String
  let abbr: String
}

struct Group: Codable, Nameable {
  let id: Int
  let name: String
}

Thus your roomsAndGroups should now be comprised of Nameable:

var roomsAndGroups: [[Nameable]]()

And in your table view's datasource methods you can fetch those nameable objects and populate your table:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  var nameable = roomsAndGroups[indexPath.section][indexPath.row]

  ...

  cell.textLabel?.text = nameable.name
  return cell
}

Option 2

Wrap your types with an enum like:

enum Wrapper {
  case auditorie(Auditorie)
  case group(Group)
}

Your roomsAndGroups and table view datasource method's change accordingly:

var roomsAndGroups: [[Wrapper]]()

...

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  var wrapper = roomsAndGroups[indexPath.section][indexPath.row]
  switch wrapper {
  case .auditorie(let auditorie):
    // Handle cell dequeuing with auditorie object
  case .group(let group):
    // Handle cell dequeuing with group object
  }
}