来自Swift中笔尖的自定义UITableViewCell


139

我正在尝试从笔尖创建自定义表格视图单元格。我在这里指的是这篇文章。我面临两个问题。

我创建了一个.xib文件,并将UITableViewCell对象拖到该文件上。我创建了的子类,UITableViewCell并将其设置为单元格的类,将Cell设置为可重用的标识符。

import UIKit

class CustomOneCell: UITableViewCell {

    @IBOutlet weak var middleLabel: UILabel!
    @IBOutlet weak var leftLabel: UILabel!
    @IBOutlet weak var rightLabel: UILabel!

    required init(coder aDecoder: NSCoder!) {
        super.init(coder: aDecoder)
    }

    override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }

    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
    }

}

在UITableViewController中,我有以下代码,

import UIKit

class ViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {

    var items = ["Item 1", "Item2", "Item3", "Item4"]

    override func viewDidLoad() {
        super.viewDidLoad()
    }

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

    override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
        let identifier = "Cell"
        var cell: CustomOneCell! = tableView.dequeueReusableCellWithIdentifier(identifier) as? CustomOneCell
        if cell == nil {
            tableView.registerNib(UINib(nibName: "CustomCellOne", bundle: nil), forCellReuseIdentifier: identifier)
            cell = tableView.dequeueReusableCellWithIdentifier(identifier) as? CustomOneCell
        }

        return cell
    }
}

这段代码没有错误,但是当我在模拟器中运行它时,它看起来像这样。

在此处输入图片说明

在情节提要中的UITableViewController中,我没有对单元执行任何操作。空白标识符,无子类。我尝试将Cell标识符添加到原型单元中,然后再次运行,但得到的结果相同。

我遇到的另一个错误是,当我尝试在UITableViewController中实现以下方法时。

override func tableView(tableView: UITableView!, willDisplayCell cell: CustomOneCell!, forRowAtIndexPath indexPath: NSIndexPath!) {

    cell.middleLabel.text = items[indexPath.row]
    cell.leftLabel.text = items[indexPath.row]
    cell.rightLabel.text = items[indexPath.row]
}

正如我所提到的文章中所示,我改变了cell参数的类型形式UITableViewCellCustomOneCell这是我的UITableViewCell的子类。但是我收到以下错误,

使用选择器'tableView:willDisplayCell:forRowAtIndexPath:'的重写方法具有不兼容的类型'(UITableView !, CustomOneCell !, NSIndexPath!)->()'

有人知道如何解决这些错误吗?这些似乎在Objective-C中工作正常。

谢谢。

编辑:我只是注意到,如果我将模拟器的方向更改为横向并将其重新设置为纵向,则会出现单元!我仍然不知道发生了什么。如果您有时间快速浏览,我在这里上传了一个Xcode项目演示了该问题。

Answers:


213

使用Swift 5和iOS 12.2,您应该尝试使用以下代码来解决问题:

CustomCell.swift

import UIKit

class CustomCell: UITableViewCell {

    // Link those IBOutlets with the UILabels in your .XIB file
    @IBOutlet weak var middleLabel: UILabel!
    @IBOutlet weak var leftLabel: UILabel!
    @IBOutlet weak var rightLabel: UILabel!

}

TableViewController.swift

import UIKit

class TableViewController: UITableViewController {

    let items = ["Item 1", "Item2", "Item3", "Item4"]

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCell")
    }

    // MARK: - UITableViewDataSource

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell

        cell.middleLabel.text = items[indexPath.row]
        cell.leftLabel.text = items[indexPath.row]
        cell.rightLabel.text = items[indexPath.row]

        return cell
    }

}

下图显示了一组约束,这些约束可与提供的代码一起使用,而没有来自Xcode的任何约束歧义消息:

在此处输入图片说明


1
感谢您的回复。但这也不起作用。我是否需要在表视图控制器中进行任何更改?因为它仍然设置为原型单元。
Isuru

1
继续使用原型单元。但是,请确保设置了良好的自动布局约束(如果使用自动布局)。
Imanou Petit 2014年

1
在这里上传了一个测试项目演示了我遇到的问题。如果有时间,可以请您看看吗?
Isuru

1
您的测试项目证实了这一点:在为.xib文件中的自定义单元格设置了一些自动布局约束之后,我能够使您的应用正常运行。如果您需要更多有关自动版式的信息,请观看此视频
Imanou Petit 2014年

2
@KirillKudaev在Swift 4中没有重命名,但在Swift 3中,我已经修复了您的编辑。
心教堂

30

这是我使用Swift 2和Xcode 7.3的方法。本示例将使用单个ViewController加载两个.xib文件-一个用于UITableView,一个用于UITableCellView。

在此处输入图片说明

对于此示例,您可以将UITableView拖放到一个空的TableNib .xib文件中。在内部,将文件的所有者设置为ViewController类,并使用出口引用tableView。

在此处输入图片说明

在此处输入图片说明

现在,您可以在视图控制器中像平常一样委派tableView

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    ...

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        // Table view delegate
        self.tableView.delegate = self
        self.tableView.dataSource = self

        ...

若要再次创建“自定义”单元格,请将“表视图单元格”对象拖放到一个空的TableCellNib .xib文件中。这次,在单元.xib文件中,您不必指定“所有者”,但是您确实需要指定自定义类和诸如“ TableCellId” 的标识符

在此处输入图片说明 在此处输入图片说明

使用所需的任何渠道创建子类

class TableCell: UITableViewCell {

    @IBOutlet weak var nameLabel: UILabel!

}

最后,回到View Controller中,您可以像这样加载并显示整个内容

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    // First load table nib
    let bundle = NSBundle(forClass: self.dynamicType)
    let tableNib = UINib(nibName: "TableNib", bundle: bundle)
    let tableNibView = tableNib.instantiateWithOwner(self, options: nil)[0] as! UIView

    // Then delegate the TableView
    self.tableView.delegate = self
    self.tableView.dataSource = self

    // Set resizable table bounds
    self.tableView.frame = self.view.bounds
    self.tableView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]

    // Register table cell class from nib
    let cellNib = UINib(nibName: "TableCellNib", bundle: bundle)
    self.tableView.registerNib(cellNib, forCellReuseIdentifier: self.tableCellId)

    // Display table with custom cells
    self.view.addSubview(tableNibView)

}

该代码显示了如何简单地加载和显示笔尖文件(表),以及如何注册一个笔尖供单元使用。

希望这可以帮助!!!


2
您能解释一下这行中的“ tableCellId”是什么吗?... self.tableView.registerNib(cellNib,forCellReuseIdentifier:self.tableCellId)....因为您尚未定义它。并且您无法在xib中手动定义标识符。没有可用的选项来定义它
PRADIP KUMAR 2016年

1
在界面构建器中,当您创建tableCell时,在“属性检查器”中定义一个标识符。相同的标识符是您在控制器中用来引用对象的标识符。let tableCellId = "myAwesomeCell"。我添加了另一张图片来帮助您。
internet-nico

16

斯威夫特4

注册笔尖

override func viewDidLoad() {
    super.viewDidLoad()
    tblMissions.register(UINib(nibName: "MissionCell", bundle: nil), forCellReuseIdentifier: "MissionCell")
}

在TableView数据源中

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
          guard let cell = tableView.dequeueReusableCell(withIdentifier: "MissionCell", for: indexPath) as? MissionCell else { return UITableViewCell() }
          return cell
    }

9

带有屏幕截图的详细解决方案

  1. 创建一个空的用户界面文件并将其命名MyCustomCell.xib

在此处输入图片说明

  1. UITableViewCellx作为您的xib文件和所有其他可视组件的根目录。

在此处输入图片说明

  1. 创建一个可可触摸类文件,其类名称MyCustomCell为的子类UITableViewCell

在此处输入图片说明 在此处输入图片说明

  1. 为您的自定义表格视图单元格设置自定义类和重用标识符。

在此处输入图片说明 在此处输入图片说明

  1. 打开助手编辑器,然后ctrl+drag为视觉组件创建插座。

在此处输入图片说明

  1. 配置一个UIViewController以使用您的自定义单元。
class MyViewController: UIViewController {

    @IBOutlet weak var myTable: UITableView!

    override func viewDidLoad {
        super.viewDidLoad()

        let nib = UINib(nibName: "MyCustomCell", bundle: nil)
        myTable.register(nib, forCellReuseIdentifier: "MyCustomCell")
        myTable.dataSource = self
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let cell = tableView.dequeueReusableCell(withIdentifier: "MyCustomCell") as? MyCustomCell {
            cell.myLabel.text = "Hello world."
            return cell
        }
        ...
    }
}

你救了我的日子。我已经复制MyHeaderView.swift了自定义单元格。在.swift为标题视图没有identifierTable View CellAttribute Inspector。所以...发生运行时错误。
马赞德

顺便说一句..为什么我们要为in .swift和in 声明相同的标识符名称tableView?.register(blahblah, forCellReuseIdentifier: "myCell")?我认为其中之一不是必需的,但是我发现两者都是必不可少的。
马赞德

嗯..可能是因为.. .xib对于自定义单元格可以包含多个,UITableViewCell所以.. .xib不足以..找到正确的单元格。
马森德

5

您没有按以下方式注册笔尖:

tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCell")

4

另一种可能对您有用的方法(这就是我的方法)是注册一个类。

假设您创建一个自定义tableView,如下所示:

class UICustomTableViewCell: UITableViewCell {...}

然后,您可以使用“ registerClass”在要显示它的任何UITableViewController中注册该单元格:

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.registerClass(UICustomTableViewCell.self, forCellReuseIdentifier: "UICustomTableViewCellIdentifier")
}

您可以按预期在行方法的单元格中调用它:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("UICustomTableViewCellIdentifier", forIndexPath: indexPath) as! UICustomTableViewCell
    return cell
}

3

为了解决“覆盖方法...具有不兼容的类型...”错误,我已将函数声明更改为

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

(是-> UITableViewCell!-末尾带有感叹号)


2

迅捷4.1.2

希伯

创建ImageCell2.swift

第1步

import UIKit

class ImageCell2: UITableViewCell {

    @IBOutlet weak var imgBookLogo: UIImageView!
    @IBOutlet weak var lblTitle: UILabel!
    @IBOutlet weak var lblPublisher: UILabel!
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

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

}

第2步 。根据Viewcontroller类

  import UIKit

    class ImageListVC: UIViewController,UITableViewDataSource,UITableViewDelegate {
    @IBOutlet weak var tblMainVC: UITableView!

    var arrBook : [BookItem] = [BookItem]()

    override func viewDidLoad() {
        super.viewDidLoad()
         //Regester Cell
        self.tblMainVC.register(UINib.init(nibName: "ImageCell2", bundle: nil), forCellReuseIdentifier: "ImageCell2")
        // Response Call adn Disply Record
        APIManagerData._APIManagerInstance.getAPIBook { (itemInstance) in
            self.arrBook = itemInstance.arrItem!
            self.tblMainVC.reloadData()
        }
    }
    //MARK: DataSource & delegate
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.arrBook.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//    [enter image description here][2]
        let cell  = tableView.dequeueReusableCell(withIdentifier: "ImageCell2") as! ImageCell2
        cell.lblTitle.text = self.arrBook[indexPath.row].title
        cell.lblPublisher.text = self.arrBook[indexPath.row].publisher
        if let authors = self.arrBook[indexPath.row].author {
            for item in authors{
                print(" item \(item)")
            }
        }
        let  url  = self.arrBook[indexPath.row].imageURL
        if url == nil {
            cell.imgBookLogo.kf.setImage(with: URL.init(string: ""), placeholder: UIImage.init(named: "download.jpeg"))
        }
        else{
            cell.imgBookLogo.kf.setImage(with: URL(string: url!)!, placeholder: UIImage.init(named: "download.jpeg"))
        }
        return cell
    }
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 90
    } 

}

2

我必须确保在创建插座时指定我是挂接到单元而不是对象的所有者。当菜单显示名称时,您必须在“对象”下拉菜单中选择它。当然,您也必须将单元格声明为您的类,而不仅仅是“ TableViewCellClass”。否则,我将继续使该类不符合密钥要求。


1

只需使用类UITableViewCell的xib 。根据需要设置UI并分配IBOutlet。在表视图的cellForRowAt()中使用它,如下所示:

//MARK: - table method

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.arrayFruit.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell:simpleTableViewCell? = tableView.dequeueReusableCell(withIdentifier:"simpleTableViewCell") as? simpleTableViewCell
    if cell == nil{
        tableView.register(UINib.init(nibName: "simpleTableViewCell", bundle: nil), forCellReuseIdentifier: "simpleTableViewCell")
        let arrNib:Array = Bundle.main.loadNibNamed("simpleTableViewCell",owner: self, options: nil)!
        cell = arrNib.first as? simpleTableViewCell
    }

    cell?.labelName.text = self.arrayFruit[indexPath.row]
    cell?.imageViewFruit.image = UIImage (named: "fruit_img")

    return cell!

}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
 return 100.0
}

在此处输入图片说明

100%正常工作(经过测试)


它说控制单元格?.labelName为零
Vignesh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.