Swift - 如何使用两种单元格类型的dequeueReusableCellWithIdentifier? (身份标识)

时间:2015-03-14 13:02:08

标签: uitableview swift xcode6

我正在尝试为事件构建表格视图,如下所示:
enter image description here

我有两个细胞原型:

  • 带有标识符" event"
  • 事件单元格
  • 分隔符,标识符为"分隔符"

另外,我有这个类代表一个日期:

class Event{

    var name:String = ""
    var date:NSDate? = nil
}

这是表控制器:

class EventsController: UITableViewController {

    //...

    var eventsToday = [Event]()
    var eventsTomorrow = [Event]()
    var eventsNextWeek = [Event]()

    override func viewDidLoad() {
        super.viewDidLoad()

        //...

        self.fetchEvents()//Fetch events from server and put each event in the right property (today, tomorrow, next week)

        //...
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let event = tableView.dequeueReusableCellWithIdentifier("event", forIndexPath: indexPath) as EventTableViewCell
        let seperator = tableView.dequeueReusableCellWithIdentifier("seperator", forIndexPath: indexPath) as SeperatorTableViewCell

        //...

        return cell
    }
}

我掌握了手头所需的所有信息,但我无法找到合适的方法。对于我重新划分多种细胞类型,我不清楚出队功能背后的机制。

我知道这个问题的范围可能看起来有点过于宽泛,但是一些指出正确方向的代码行将会非常受欢迎。此外,我认为它会使很多用户受益,因为我没有找到任何Swift示例。

提前致谢!

1 个答案:

答案 0 :(得分:4)

基本方法是您必须实施numberOfRowsInSectioncellForRowAtIndexPath(如果您的表有多个部分,numberOfSectionsInTableView也是如此)。但每次调用cellForRowAtIndexPath只会创建一个单元格,因此您必须以编程方式执行此操作,查看indexPath以确定它是什么类型的单元格。例如,要按照您的建议实现它,它可能看起来像:

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return eventsToday.count + eventsTomorrow.count + eventsNextWeek.count + 3 // sum of the three array counts, plus 3 (one for each header)
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var index = indexPath.row

    // see if we're the "today" header

    if index == 0 {
        let separator = tableView.dequeueReusableCellWithIdentifier("separator", forIndexPath: indexPath) as SeparatorTableViewCell

        // configure "today" header cell

        return separator
    }

    // if not, adjust index and now see if we're one of the `eventsToday` items

    index--

    if index < eventsToday.count {
        let eventCell = tableView.dequeueReusableCellWithIdentifier("event", forIndexPath: indexPath) as EventTableViewCell
        let event = eventsToday[index]

        // configure "today" `eventCell` cell using `event`

        return eventCell
    }

    // if not, adjust index and see if we're the "tomorrow" header

    index -= eventsToday.count

    if index == 0 {
        let separator = tableView.dequeueReusableCellWithIdentifier("separator", forIndexPath: indexPath) as SeparatorTableViewCell

        // configure "tomorrow" header cell

        return separator
    }

    // if not, adjust index and now see if we're one of the `eventsTomorrow` items

    index--

    if index < eventsTomorrow.count {
        let eventCell = tableView.dequeueReusableCellWithIdentifier("event", forIndexPath: indexPath) as EventTableViewCell
        let event = eventsTomorrow[index]

        // configure "tomorrow" `eventCell` cell using `event`

        return eventCell
    }

    // if not, adjust index and see if we're the "next week" header

    index -= eventsTomorrow.count

    if index == 0 {
        let separator = tableView.dequeueReusableCellWithIdentifier("separator", forIndexPath: indexPath) as SeparatorTableViewCell

        // configure "next week" header cell

        return separator
    }

    // if not, adjust index and now see if we're one of the `eventsToday` items

    index--

    assert (index < eventsNextWeek.count, "Whoops; something wrong; `indexPath.row` is too large")

    let eventCell = tableView.dequeueReusableCellWithIdentifier("event", forIndexPath: indexPath) as EventTableViewCell
    let event = eventsNextWeek[index]

    // configure "next week" `eventCell` cell using `event`

    return eventCell
}

话虽如此,我真的不喜欢那种逻辑。我宁愿代表&#34;今天&#34;,&#34;明天&#34; &#34;下周&#34;分隔符单元格作为标题,并使用表格视图具有的节逻辑。

例如,您可以将表实现为包含三个部分的表,而不是将表表示为包含8行的单个表,而每个表分别包含2个,1个和2个项。那看起来像是:

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 3
}

override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    switch section {
    case 0:
        return "Today"
    case 1:
        return "Tomorrow"
    case 2:
        return "Next week"
    default:
        return nil
    }
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    switch section {
    case 0:
        return eventsToday.count
    case 1:
        return eventsTomorrow.count
    case 2:
        return eventsNextWeek.count
    default:
        return 0
    }
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let eventCell = tableView.dequeueReusableCellWithIdentifier("event", forIndexPath: indexPath) as EventTableViewCell

    var event: Event!

    switch indexPath.section {
    case 0:
        event = eventsToday[indexPath.row]
    case 1:
        event = eventsTomorrow[indexPath.row]
    case 2:
        event = eventsNextWeek[indexPath.row]
    default:
        event = nil
    }

    // populate eventCell on the basis of `event` here

    return eventCell
}

多部分方法从表格视图更加逻辑地映射到底层模型,所以我采用这种模式,但你有两种方法,你可以决定。