【问题标题】:tableView.dequeueReusableCellWithIdentifier VS tableView.cellForRowAtIndexPathtableView.dequeueReusableCellWithIdentifier VS tableView.cellForRowAtIndexPath
【发布时间】:2015-11-06 05:12:33
【问题描述】:

我的 Xcode 是 7.1。模拟器是iPhone6。
通常我使用dequeueResuableCellWithIdentifier,但这次我遇到了问题。

我的问题是:
选择新行后,它不会清除我的orangeColor()。但是取消选择 indexPath 的打印行是正确的。

我的解决方案是:
我从
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as! MyCell;
改变了 到
let cell = tableView.cellForRowAtIndexPath(indexPath) as! MyCell;
然后它解决了我的问题。背景颜色为clearColor()

这是我的文件:
MyCell.swift :

import UIKit

class MyCell: UITableViewCell {
    @IBOutlet weak var myLabel : UILabel!
    @IBOutlet weak var myWebView : UIWebView!;
    //@IBOutlet weak var myView : UIView!;
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code.
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

ViewController.swift :

import UIKit

class ViewController: UIViewController,UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableViewObject: UITableView!

    var fruits = ["Apple", "Banana","Cherry", "Durian", "ElderBerry"];
    var selectedIndexPath : NSIndexPath?;
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableViewObject.delegate = self;
        self.tableViewObject.dataSource = self;
        // Do any additional setup after loading the view, typically from a nib.
    }
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        return fruits.count;
    }
    func loadCellContent(acell : UITableViewCell, indexPath : NSIndexPath, color: UIColor){
        let cell = acell as! MyCell;
        cell.myLabel.text = String(UnicodeScalar(65 + indexPath.row));
        cell.myWebView.loadHTMLString(fruits[indexPath.row], baseURL: nil);
        cell.myWebView.scrollView.bounces = false;
        cell.myWebView.scrollView.scrollEnabled = false;
        cell.myWebView.userInteractionEnabled = false;
        cell.backgroundColor = color;
        cell.myLabel.backgroundColor = color;
        cell.myWebView.backgroundColor = color;
    }
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
        let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as! MyCell;
        self.loadCellContent(cell, indexPath: indexPath, color: UIColor.clearColor());
        return cell;
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int{
        return 1;
    }
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        //let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as! MyCell;
        let cell = tableView.cellForRowAtIndexPath(indexPath) as! MyCell;
        self.loadCellContent(cell, indexPath: indexPath, color : UIColor.orangeColor());
    }
    func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
        //let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as! MyCell;
        let cell = tableView.cellForRowAtIndexPath(indexPath) as! MyCell;
        self.loadCellContent(cell, indexPath: indexPath,color: UIColor.clearColor());
        print("Hellos", indexPath.row);

    }
}

我的问题是:
1.dequeueReusableCellWithIdentifercellForRowAtIndexPath的主要区别是什么?
2. 何时使用第一个或第二个,我怎么知道? 这次我使用从一个教程到另一个教程的试验/错误。

更新:
我的背景是物理学和一点点计算机科学。请不要因为我的幼稚问题而生气。

【问题讨论】:

  • dequeueReusableCellWithIdentifer 只能用于cellForRowAtIndexPath 的实现中。
  • @Anbu.Karthik 感谢您的搜索。我现在对dequeueReusableCellWithIndentifier() 有了更多的了解。我的理解是dequeue 会重用内存,但cellForRowAtIndexPath 不会重用内存。我对吗?我仍然不清楚为什么第二个有效,但第一个无效。
  • @rmaddy 对不起,我不明白。你能举个例子给我解释一下吗?
  • @rmaddy。我现在明白了!谢谢你:)

标签: ios swift uitableview


【解决方案1】:

tableview 试图在内存中始终没有所有索引路径的单元对象实例:

  • “dequeueReusableCellWithIdentifer”回收或创建单元格,应在“cellForRow...”中调用。这总是返回一个单元格实例,可以是新的,也可以是以前不再可见的。之后您准备单元格以供显示。

  • 'cellForRowAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell? // 如果单元格不可见或索引路径超出范围则返回 nil' 这不会创建单元格,只允许您访问它们。我认为应该尽量避免,防止意外泄漏和其他对tableView的干扰。

关于您的“setSelected”问题:

  • 最好在单元类中实现重用准备(将所有值设置为默认值)。
  • 您不需要在“didSelectRow”中再次加载单元格内容(用户此时只是点击它,所以它已加载)
  • 您可能需要在单元格的“setSelected”中更改橙色/透明颜色

【讨论】:

  • 您对dequeueReusableCellWithIdentifer 总是返回一个单元格实例 的评论根本不正确。在很多情况下它可以返回nil
  • @rmaddy - 对您的观察稍作改进:如果您使用dequeueReusableCellWithIdentifier:indexPath:(OP 在他的代码示例中使用,并且 Andrei 可能指的是...他应该澄清),它总是返回一个单元格实例。另一方面,如果您指的是较旧的dequeueReusableCellWithIdentifier:,如果没有与该标识符关联的类/nib/原型并且重用队列中没有单元格,则可以返回nil。跨度>
  • @Rob 很好的说明。我应该更清楚我指的是dequeueReusableCellWithIdentifier: 方法,而不是也采用索引路径的方法。
【解决方案2】:

这两种方法有不同的用途。

  • dequeueReusableCellWithIdentifier:indexPath: 会在必要时实例化一个新单元格,但如果有可用的单元格,则会重用之前已从屏幕上滚出的单元格。

    你只能从tableView:cellForRowAtIndexPath:调用这个方法。

  • cellForRowAtIndexPath: 方法(不要与名称相似的tableView:cellForRowAtIndexPath: 方法混淆)不会实例化新单元格,而仅用于获取对当前可见的先前实例化单元格的引用。如果单元格不可见(例如,已滚动到屏幕外),则返回 nil

    您在tableView:didSelectRowAtIndexPath:tableView:didDeselectRowAtIndexPath: 等方法中使用此方法,因为您只是尝试获取对现有单元格的引用,而不是实例化新单元格。

--

注意,在您的代码示例中,您不仅从tableView:cellForRowAtIndexPath: 调用loadCellContent,还从tableView:didSelectRowAtIndexPath:tableView:didDeselectRowAtIndexPath: 调用。我建议将单元格的初始配置(例如,loadCellContent,您只能从tableView:cellForRowAtIndexPath: 调用)与背景颜色的调整(您将在didSelect...didDeselect... 中进行)分开)。后两种方法通常不会重新配置整个单元格,而只是更新背景颜色(或执行任何适合显示选择的装饰)。

您还想确保tableView:cellForRowAtIndexPath: 在配置背景颜色时检查是否选择了单元格。用户可能会选择一个单元格,将其滚动到屏幕外,然后将其滚动回屏幕,在这种情况下,tableView:cellForRowAtIndexPath: 必须检查该单元格是否被选中才能设置背景颜色。

例如:

// MARK: Cell configuration

func loadContentForCell(cell: UITableViewCell, indexPath: NSIndexPath) {
    // do whatever you need here; I'm just going to set the `textLabel`
    cell.textLabel?.text = "Row \(indexPath.row)"
}

func updateBackgroundColorForCell(cell: UITableViewCell?) {
    cell?.contentView.backgroundColor = cell?.selected == true ? UIColor.redColor() : UIColor.whiteColor()
}

// MARK: UITableViewDataSource

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

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
    
    loadContentForCell(cell, indexPath: indexPath)
    updateBackgroundColorForCell(cell)
    
    return cell
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.cellForRowAtIndexPath(indexPath)
    updateBackgroundColorForCell(cell)
}

override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.cellForRowAtIndexPath(indexPath)
    updateBackgroundColorForCell(cell)
}

【讨论】:

  • 谢谢。今后。我将按照您的示例格式,我很清楚如何实现这些功能:]
猜你喜欢
  • 1970-01-01
  • 2015-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-17
  • 2011-09-18
  • 1970-01-01
相关资源
最近更新 更多