dequeueReusableCellWithIdentifier:forIndexPath:VS dequeueReusableCellWithIdentifier: [英] dequeueReusableCellWithIdentifier:forIndexPath: VS dequeueReusableCellWithIdentifier:

查看:92
本文介绍了dequeueReusableCellWithIdentifier:forIndexPath:VS dequeueReusableCellWithIdentifier:的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已阅读



非常简单,但当我将 tableView:cellForRowAtIndexPath:方法分别更改为1,2,3,4个案例时:



案例1:

 覆盖func tableView(tableView:UITableView,cellForRowAtIndexPath indexPath: NSIndexPath) - > UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(Cell,forIndexPath:indexPath)
cell = tableView.dequeueReusableCellWithIdentifier(Cell,forIndexPath:indexPath)

cell.textLabel ?。text = items [indexPath.row]
返回单元格
}

情况2:

 覆盖func tableView(tableView:UITableView,cellForRowAtIndexPath indexPath:NSIndexPath) - > UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(Cell,forIndexPath:indexPath)
cell = tableView.dequeueReusableCellWithIdentifier(Cell)!

cell.textLabel?.text = items [indexPath.row]
return cell
}

案例3:

 覆盖func tableView(tableView:UITableView,cellForRowAtIndexPath indexPath:NSIndexPath ) - > UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(Cell)!
cell = tableView.dequeueReusableCellWithIdentifier(Cell,forIndexPath:indexPath)

cell.textLabel?.text = items [indexPath.row]
return cell
}

案例4:

 覆盖func tableView(tableView:UITableView,cellForRowAtIndexPath indexPath:NSIndexPath) - > UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(Cell)!
cell = tableView.dequeueReusableCellWithIdentifier(Cell)!

cell.textLabel?.text = items [indexPath.row]
return cell
}

案例1,2(不起作用):





案例3,4(工作正常):





如何解释?我认为从另一个角度理解这两种方法确实很有帮助,任何意见都是受欢迎的。

解决方案

在每种情况下,你都是每行出列两个单元格。在情况1和2中,首先调用(Cell,forIndexPath:indexPath)版本。在这种情况下,表格视图以每行两个单元格结束,一个完全重叠并遮挡另一个。你可以在视图检查器中看到这个,因为你可以修改视角来看后面:





(我修改了 cellForRowAtIndexPath 这样的代码:

 覆盖func tableView(tableView:UITableView,cellForRowAtIndexPath indexPath:NSIndexPath) - > UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(plainCell,forIndexPath:indexPath)
cell。 textLabel!.text =行的第一个单元格\(indexPath.row)
cell = tableView.dequeueReusableCellWithIdentifier(plainCell,forIndexPath:indexPath)
cell.textLabel!.text =second cell for row \(indexPath.row)
print(返回的单元格是\(单元格))
返回单元格
}

为每个单元格指定不同的文本标签。)在情况3和4中,首先调用(Cell)版本,表视图每行只有一个单元格。



为什么不同的行为?如果您创建 UITableViewCell 的自定义子类并在故事板中使用它,则可以覆盖各种方法并添加 print()陈述看看发生了什么。特别是, awakeFromNib didMoveToSuperView deinit 。发生的情况是,在情况1和2中,创建了第一个单元格(awakeFromNib)并立即将其添加(didMoveToSuperView)到superview,可能是表视图或其子视图之一。在情况3和4中,创建了第一个单元格但未添加到超级视图中。相反,一段时间后,单元格被释放(deinit)。



(注意,如果第二个单元格使用(单元格)出列, forIndexPath:indexPath)版本,它也会立即添加到superview。但是,如果第二个单元格使用(Cell)出列版本,只有在 cellForRowAtIndexPath 方法返回后才会将其添加到superview 。)



所以关键的区别在于(Cell,forIndexPath:indexPath)版本导致单元格被立即添加到表格视图中,甚至在<$ c之前$ c> cellForRowAtIndexPath 已完成。这在您提到的问题/答案中暗示,因为它表明出列单元格的大小正确。



一旦添加到超级视图,第一个单元格就无法解除分配,因为它的超级视图仍然有一个强引用。如果单元格使用(单元格)版本出列,则它们不会添加到超级视图中,因此一旦 cell 变量被重新分配,因此它们被解除分配。



希望所有这些都有意义。


I have read this question and think that I understand the difference between the two methods until I find a strange example:

Set table view cell's style be Basic, Identifier be Cell in Storyboard, code as below:

import UIKit

class TableViewController: UITableViewController {
    var items: [String]!

    override func viewDidLoad() {
        super.viewDidLoad()
        items = ["first", "second", "third"]
    }

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

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        // either works fine
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell")! // let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)

        cell.textLabel?.text = items[indexPath.row]
        return cell
    }
}

Very simple, but when I change the tableView:cellForRowAtIndexPath: method to 1, 2, 3, 4 cases respectively:

Case 1:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
    cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)

    cell.textLabel?.text = items[indexPath.row]
    return cell
}

Case 2:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
    cell = tableView.dequeueReusableCellWithIdentifier("Cell")!

    cell.textLabel?.text = items[indexPath.row]
    return cell
}

Case 3:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier("Cell")!
    cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)

    cell.textLabel?.text = items[indexPath.row]
    return cell
}

Case 4:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier("Cell")!
    cell = tableView.dequeueReusableCellWithIdentifier("Cell")!

    cell.textLabel?.text = items[indexPath.row]
    return cell
}

Case 1, 2 (doesn't work):

Case 3, 4 (works fine):

How to explain? I think it really helps to understand these two methods from another perspective, any opinion is welcome.

解决方案

In each case, you are dequeueing two cells for each row. In cases 1 and 2, you call the ("Cell", forIndexPath: indexPath) version first. In this case the table view ends up with two cells for each row, one completely overlapping and obscuring the other. You can see this in the view inspector since you can amend the angle of view to see behind:

(I amended the cellForRowAtIndexPath code like this:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier("plainCell", forIndexPath: indexPath)
    cell.textLabel!.text = "First cell for row \(indexPath.row)"
    cell = tableView.dequeueReusableCellWithIdentifier("plainCell", forIndexPath: indexPath)
    cell.textLabel!.text = "Second cell for row \(indexPath.row)"
    print("Cell being returned is \(cell)")
    return cell
}

to given different text labels to each cell.) In cases 3 and 4, where you call the ("Cell") version first, the table view has only one cell for each row.

Why the different behaviour? If you create a custom subclass of UITableViewCell and use that in your storyboard, you can then override various methods and add print() statements to see what's happening. In particular, awakeFromNib, didMoveToSuperView, and deinit. What transpires is that in cases 1 and 2, the first cell is created (awakeFromNib) and immediately added (didMoveToSuperView) to a superview, presumably the table view or one of its subviews. In cases 3 and 4, the first cell is created but is not added to a superview. Instead some time later, the cell is deallocated (deinit).

(Note that if the second cell is dequeued using the ("Cell", forIndexPath: indexPath) version, it too is added immediately to a superview. However, if the second cell is dequeued using the ("Cell") version, it is only added to a superview after the cellForRowAtIndexPath method has returned.)

So the key difference is that the ("Cell", forIndexPath: indexPath) version results in the cell being added immediately to the table view, before even the cellForRowAtIndexPath has completed. This is hinted at in the question/answer to which you refer, since it indicates that the dequeued cell will be correctly sized.

Once added to the superview, the first cell cannot be deallocated since there is still a strong reference to it from its superview. If the cells are dequeued with the ("Cell") version, they are not added to the superview, there is consequently no strong reference to them once the cell variable is reassigned, and they are consequently deallocated.

Hope all that makes sense.

这篇关于dequeueReusableCellWithIdentifier:forIndexPath:VS dequeueReusableCellWithIdentifier:的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆