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
Custom UITableViewCell from nib in Swift
提问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 UITableViewCell
and 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.
这段代码没有错误,但是当我在模拟器中运行它时,它看起来像这样。
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 cell
parameter's type form UITableViewCell
to CustomOneCell
which 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 的任何约束歧义消息:
回答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。
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。
and
和
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”
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
带截图的详细解决方案
- Create an empty user interface file and name it
MyCustomCell.xib
.
- 创建一个空的用户界面文件并将其命名为
MyCustomCell.xib
.
- Add a
UITableViewCell
as the root of your xib file and any other visual components you want.
- 添加 a
UITableViewCell
作为您的 xib 文件和您想要的任何其他可视组件的根目录。
- Create a cocoa touch class file with class name
MyCustomCell
as a subclass ofUITableViewCell
.
- 创建一个可可触摸类文件,类名
MyCustomCell
作为UITableViewCell
.
- Set the custom class and reuse identifier for your custom table view cell.
- 为您的自定义表格视图单元格设置自定义类和重用标识符。
- Open the assistant editor and
ctrl+drag
to create outlets for your visual components.
- 打开辅助编辑器并
ctrl+drag
为您的可视组件创建插座。
- Configure a
UIViewController
to use your custom cell.
- 配置 a
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
}
...
}
}
回答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
}
100% working without any issue (Tested)
100% 工作没有任何问题(已测试)