ios 来自 Swift 笔尖的自定义 UITableViewCell

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25541786/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 02:04:55  来源:igfitidea点击:

Custom UITableViewCell from nib in Swift

iosuitableviewswiftios8

提问by Isuru

I'm trying to create a custom table view cell from a nib. I'm referring to this article here. I'm facing two issues.

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

I created a .xib file with a UITableViewCell object dragged on to it. I created a subclass of UITableViewCelland set it as the cell's class and Cellas the reusable identifier.

我创建了一个 .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
    }

}

In the UITableViewController I have this code,

在 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
    }
}

This code complies with no errors but when I run it in the simulator, it looks like this.

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

enter image description here

在此处输入图片说明

In the UITableViewController in the storyboard I haven't done anything to the cell. Blank identifier and no subclass. I tried adding the Cellidentifier to the prototype cell and ran it again but I get the same result.

在故事板的 UITableViewController 中,我没有对单元格做任何事情。空白标识符且没有子类。我尝试将单元标识符添加到原型单元并再次运行它,但我得到了相同的结果。

Another error I faced is, when I tried to implement the following method in the UITableViewController.

我遇到的另一个错误是,当我尝试在 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]
}

As shown in the article I mentioned I changed the cellparameter's type form UITableViewCellto CustomOneCellwhich is my subclass of UITableViewCell. But I get the following error,

如我提到的文章中所示,我将cell参数的类型形式UITableViewCell更改CustomOneCell为我的 UITableViewCell 子类。但我收到以下错误,

Overriding method with selector 'tableView:willDisplayCell:forRowAtIndexPath:' has incompatible type '(UITableView!, CustomOneCell!, NSIndexPath!) -> ()'

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

Anyone have any idea how to resolve these errors? These seemed to work fine in Objective-C.

任何人都知道如何解决这些错误?这些在 Objective-C 中似乎运行良好。

Thank you.

谢谢你。

EDIT: I just noticed if I change the simulator's orientation to landscape and turn it back to portrait, the cells appear! I still couldn't figure out what's going on. I uploaded an Xcode project heredemonstrating the problem if you have time for a quick look.

编辑:我刚刚注意到,如果我将模拟器的方向更改为横向并将其转回纵向,则会出现单元格!我仍然无法弄清楚发生了什么。如果您有时间快速查看,我在此处上传了一个 Xcode 项目演示该问题。

回答by Imanou Petit

With Swift 5 and iOS 12.2, you should try the following code in order to solve your problem:

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

CustomCell.swift

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

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
    }

}


The image below shows a set of constraints that work with the provided code without any constraints ambiguity message from Xcode:

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

enter image description here

在此处输入图片说明

回答by internet-nico

Here's my approach using Swift 2 and Xcode 7.3. This example will use a single ViewController to load two .xib files -- one for a UITableView and one for the UITableCellView.

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

enter image description here

在此处输入图片说明

For this example you can drop a UITableView right into an empty TableNib.xib file. Inside, set the file's ownerto your ViewController class and use an outlet to reference the tableView.

对于本示例,您可以将 UITableView 直接放入空的TableNib .xib文件中。在里面,将文件的所有者设置为您的 ViewController 类并使用插座来引用 tableView。

enter image description here

在此处输入图片说明

and

enter image description here

在此处输入图片说明

Now, in your view controller, you can delegate the tableView as you normally would, like so

现在,在您的视图控制器中,您可以像往常一样委托 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

        ...

To create your Custom cell, again, drop a Table View Cell object into an empty TableCellNib.xib file. This time, in the cell .xib file you don't have to specify an "owner" but you do need to specify a Custom Classand an identifierlike "TableCellId"

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

enter image description hereenter image description here

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

Create your subclass with whatever outlets you need like so

使用您需要的任何插座创建您的子类

class TableCell: UITableViewCell {

    @IBOutlet weak var nameLabel: UILabel!

}

Finally... back in your View Controller, you can load and display the entire thing like so

最后......回到你的视图控制器,你可以像这样加载和显示整个东西

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)

}

The code shows how you can simply load and display a nib file (the table), and second how to register a nib for cell use.

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

Hope this helps!!!

希望这可以帮助!!!

回答by Gurjinder Singh

Swift 4

斯威夫特 4

Register Nib

注册笔尖

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

In TableView DataSource

在 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
    }

回答by Derek Soike

Detailed Solution with Screenshots

带截图的详细解决方案

  1. Create an empty user interface file and name it MyCustomCell.xib.
  1. 创建一个空的用户界面文件并将其命名为MyCustomCell.xib.

enter image description here

在此处输入图片说明

  1. Add a UITableViewCellas the root of your xib file and any other visual components you want.
  1. 添加 aUITableViewCell作为您的 xib 文件和您想要的任何其他可视组件的根目录。

enter image description here

在此处输入图片说明

  1. Create a cocoa touch class file with class name MyCustomCellas a subclass of UITableViewCell.
  1. 创建一个可可触摸类文件,类名MyCustomCell作为UITableViewCell.

enter image description hereenter image description here

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

  1. Set the custom class and reuse identifier for your custom table view cell.
  1. 为您的自定义表格视图单元格设置自定义类和重用标识符。

enter image description hereenter image description here

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

  1. Open the assistant editor and ctrl+dragto create outlets for your visual components.
  1. 打开辅助编辑器并ctrl+drag为您的可视组件创建插座。

enter image description here

在此处输入图片说明

  1. Configure a UIViewControllerto use your custom cell.
  1. 配置 aUIViewController以使用您的自定义单元格。
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
        }
        ...
    }
}

回答by Sujan

You did not register your nib as below:

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

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

回答by Ethan Kay

Another method that may work for you (it's how I do it) is registering a class.

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

Assume you create a custom tableView like the following:

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

class UICustomTableViewCell: UITableViewCell {...}

You can then register this cell in whatever UITableViewController you will be displaying it in with "registerClass":

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

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

And you can call it as you would expect in the cell for row method:

您可以在单元格中按照您期望的方式调用它 for row 方法:

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

回答by tse

For fix the "Overriding method... has incompatible type..."error I've changed the function declaration to

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

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

(was -> UITableViewCell!-- with exclamation mark at the end)

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

回答by user3263340

swift 4.1.2

快速 4.1.2

xib.

xib.

Create ImageCell2.swift

创建 ImageCell2.swift

Step 1

第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)
    }

}

step 2 . According Viewcontroller class

第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
    } 

}

回答by buckleyJohnson

I had to make sure that when creating the outlet to specify that I was hooking to the cell, not the object's owner. When the menu appears to name it you have to select it in the 'object' dropdown menu. Of course you must declare the cell as your class too, not just 'TableViewCellClass'. Otherwise I would keep getting the class not key compliant.

我必须确保在创建插座时指定我正在连接到单元格,而不是对象的所有者。当菜单出现命名时,您必须在“对象”下拉菜单中选择它。当然,您也必须将单元格声明为您的类,而不仅仅是“TableViewCellClass”。否则我会继续让课程不符合关键要求。

回答by Mr.Javed Multani

Simple take a xib with class UITableViewCell. Set the UI as per reuirement and assign IBOutlet. Use it in cellForRowAt() of table view like this:

简单地使用类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
}

enter image description here

在此处输入图片说明

100% working without any issue (Tested)

100% 工作没有任何问题(已测试)