ChatGPT解决这个技术问题 Extra ChatGPT

从 Swift 中的 nib 自定义 UITableViewCell

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

我创建了一个带有 UITableViewCell 对象的 .xib 文件。我创建了一个 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
    }
}

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

https://i.stack.imgur.com/sElI3m.png

在情节提要的 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]
}

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

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

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

谢谢你。

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


I
Imanou Petit

使用 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 的任何约束歧义消息:

https://i.stack.imgur.com/inEmw.png


感谢您的回复。但这也没有用。我需要更改表格视图控制器中的任何内容吗?因为它仍然设置为原型单元。
继续使用原型细胞。但请确保您设置了良好的自动布局约束(如果您使用自动布局)。
我上传了一个测试项目 here,展示了我遇到的问题。如果你有时间可以看看吗?
您的测试项目证实了这一点:在.xib 文件中为您的自定义单元格设置一些自动布局约束后,我能够使您的应用程序正常工作。如果您需要了解有关自动布局的更多信息,请查看 this video
@KirillKudaev 它没有在 Swift 4 中重命名,而是在 Swift 3 中:我已经修复了您的编辑。
i
internet-nico

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

https://i.stack.imgur.com/D3GY0.png

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

https://i.stack.imgur.com/ru1hA.png

https://i.stack.imgur.com/SXkze.png

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

        ...

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

https://i.stack.imgur.com/EFvT3.png

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

class TableCell: UITableViewCell {

    @IBOutlet weak var nameLabel: UILabel!

}

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

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)

}

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

希望这可以帮助!!!


你能解释一下这一行中的“tableCellId”是什么...... self.tableView.registerNib(cellNib, forCellReuseIdentifier: self.tableCellId)....因为你还没有定义那是什么。并且您不能在 xib 中手动定义标识符.. 没有选项可以定义它
在界面构建器中,当您创建 tableCell 时,在“属性检查器”中定义一个标识符。您在控制器中使用相同的标识符来引用对象。 let tableCellId = "myAwesomeCell"。我添加了另一张图片来帮助你。
B
Bruno Bieri

斯威夫特 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
}

D
Derek Soike

带截图的详细解决方案

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

https://i.stack.imgur.com/rSOjZ.png

添加一个 UITableViewCell 作为您的 xib 文件的根目录以及您想要的任何其他可视组件。

https://i.stack.imgur.com/MyQ6n.png

创建一个类名为 MyCustomCell 的 cocoa touch 类文件作为 UITableViewCell 的子类。

https://i.stack.imgur.com/POlA9.png

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

https://i.stack.imgur.com/q5J6a.png

打开助手编辑器并 ctrl+drag 为您的视觉组件创建插座。

https://i.stack.imgur.com/L9Hyx.png

配置 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。标题视图的 .swiftAttribute InspectorTable View Cell 中没有 identifier。所以...发生了运行时错误。
顺便说一句..为什么我们在 .swifttableView?.register(blahblah, forCellReuseIdentifier: "myCell") 中为标识符声明了相同的名称?我认为其中一个不是必需的,但是..我发现两者都是必不可少的。
嗯.. 这可能是因为.. 自定义单元格的 .xib 可以包含多个 UITableViewCell 所以.. .xib 不足以.. 找到正确的单元格。
该解决方案完全符合我的要求,非常感谢。
k
kalpesh

迅捷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
    } 

}

E
Eric Aya

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

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

E
Ethan Kay

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

假设您创建了一个自定义 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
}

t
tse

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

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

(原为 -> UITableViewCell! - 末尾有感叹号)


b
buckleyJohnson

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


M
Mr.Javed Multani

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

https://i.stack.imgur.com/p0vfF.png

100% 正常工作(已测试)


它说控制单元?.labelName 是 nil
B
Bruno Bieri

此行在 TableView 单元格中添加:

static var nib  : UINib{
    return UINib(nibName: identifier, bundle: nil)
}

static var identifier : String{
    return String(describing: self)    
}

    

并在视图控制器中注册,如

此行在 viewDidLoad 中使用

tableview.register(TopDealLikedTableViewCell.nib, forCellReuseIdentifier: TopDealLikedTableViewCell.identifier)

索引路径处的行单元格

if let cell = tableView.dequeueReusableCell(withIdentifier:
    TopDealLikedTableViewCell.identifier) as? TopDealLikedTableViewCell{
    return cell
}

return UITableViewCell()

B
Bruno Bieri

设置在单元格上

static var identifier : String {
    return String(describing: self)   
}

static var nib : UINib {
    return UINib(nibName: identifier, bundle: nil)
}