在 Swift 中从 nib 自定义 UITableViewCell

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

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

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

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

enter image description here

在故事板中的 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:’has compulated type’(UITableView! ,CustomOneCell! ,NSIndexPath!)-> ()’重写方法

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

谢谢你。

编辑: 我刚刚注意到,如果我改变模拟器的方向,以横向,并把它回到肖像,细胞出现!我还是不明白发生了什么。我上传了一个 Xcode 项目 给你,如果您有时间快速查看一下,就会发现这个问题。

217780 次浏览

在 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 的模糊消息:

enter image description here

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

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

(叹号是 -> UITableViewCell!)

下面是我使用 Swift 2和 Xcode 7.3的方法。这个示例将使用一个 ViewController 来加载两个。Xib 文件——一个用于 UITableView,一个用于 UITableCellView。

enter image description here

对于这个示例,您可以将 UITableView 直接放到一个空的 TableNib.xib 文件中。在内部,将 文件的主人设置为 ViewController 类,并使用一个插座引用 tableView。

enter image description here

还有

enter image description here

现在,在视图控制器中,可以像通常那样委托 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 文件不需要指定“ owner”,但需要指定 定制课程标识符,如“ TableCellId”

enter image description here enter image description here

用你需要的任何出口创建你的子类

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 以供单元格使用。

希望这个能帮上忙! ! !

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

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

class UICustomTableViewCell: UITableViewCell {...}

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

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

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

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

简单取一个类 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% 工作无任何问题(测试)

Swift 4

注册表 Nib

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
}

你没有注册你的笔尖如下:

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

迅捷4.1.2

西布。

创建 ImageCell2.swift

第一步

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
}


}

具有截图的详细解决方案

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

enter image description here

  1. 添加一个 UITableViewCell作为 xib 文件的根以及任何其他所需的可视化组件。

enter image description here

  1. 创建一个类名为 MyCustomCell的可可触摸类文件作为 UITableViewCell的子类。

enter image description here enter image description here

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

enter image description here enter image description here

  1. 打开助理编辑器和 ctrl+drag,为可视组件创建出口。

enter image description here

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


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

这一行添加到 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)

Indexpath 行的单元格

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


return UITableViewCell()

设置在手机上

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


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