我想使用具有不同自定义 tableViewCells 的 UITableview。我的 3 个细胞是这样的:
Cell1:应该有一个图像和一个标签。
Cell2:应该有两个标签。
Cell3:应该有一个dayPicker。
我不想为单元格编写标签。我如何在 Swift 中管理它。我必须为每个单元格编写自己的类吗?我可以使用一个 tableviewController 吗?如何在不同的单元格中填充数据?
我想生成一个tableView,就像iOS设备的联系人应用程序一样。
让我先回答你的问题。
我必须为每个单元编写一个自己的类吗?=> 是的,我相信是的。至少,我会那样做。
我可以使用一个 tableviewController 吗?=> 是的,你可以。但是,您也可以在视图控制器中拥有一个表格视图。
如何在不同的单元格中填充数据? => 根据条件,您可以在不同的单元格中填充数据。例如,假设您希望前两行类似于第一种类型的单元格。因此,您只需创建/重用第一种类型的单元格并设置它的数据。当我给你看屏幕截图时,我想会更清楚。
让我举一个在 ViewController 中使用 TableView 的示例。一旦你理解了主要概念,那么你可以尝试任何你想要的修改。
第 1 步:创建 3 个自定义 TableViewCells。我将它命名为 FirstCustomTableViewCell、SecondCustomTableViewCell、ThirdCustomTableViewCell。您应该使用更有意义的名称。
https://i.stack.imgur.com/8Ek2s.png
第 2 步:转到 Main.storyboard 并将 TableView 拖放到 View Controller 中。现在,选择表格视图并转到身份检查器。将“Prototype Cells”设置为 3。在这里,您刚刚告诉 TableView 您可能有 3 种不同类型的单元格。
https://i.stack.imgur.com/RrXOG.png
第 3 步:现在,在 TableView 和身份检查器中选择第一个单元格,将“FirstCustomTableViewCell”放入自定义类字段中,然后在属性检查器中将标识符设置为“firstCustomCell”。
https://i.stack.imgur.com/ksDgK.png
https://i.stack.imgur.com/fOEBF.png
对所有其他人做同样的事情——分别将他们的自定义类设置为“SecondCustomTableViewCell”和“ThirdCustomTableViewCell”。还将标识符连续设置为 secondCustomCell 和 thirdCustomCell。
第 4 步:编辑自定义单元类并根据需要添加出口。我根据您的问题对其进行了编辑。
PS:您需要将插座放在类定义下。
所以,在 FirstCustomTableViewCell.swift 中,在
class FirstCustomTableViewCell: UITableViewCell {
你会放你的标签和图像视图出口。
@IBOutlet weak var myImageView: UIImageView!
@IBOutlet weak var myLabel: UILabel!
并在 SecondCustomTableViewCell.swift 中添加两个标签,例如-
import UIKit
class SecondCustomTableViewCell: UITableViewCell {
@IBOutlet weak var myLabel_1: UILabel!
@IBOutlet weak var myLabel_2: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
和 ThirdCustomTableViewCell.swift 应该看起来像 -
import UIKit
class ThirdCustomTableViewCell: UITableViewCell {
@IBOutlet weak var dayPicker: UIDatePicker!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
第 5 步:在您的 ViewController 中,为您的 TableView 创建一个 Outlet 并设置来自情节提要的连接。此外,您需要在类定义中添加 UITableViewDelegate 和 UITableViewDataSource 作为协议列表。所以,你的类定义应该看起来像 -
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
之后将表视图的 UITableViewDelegate 和 UITableViewDatasource 附加到控制器。此时您的 viewController.swift 应该看起来像 -
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
PS:如果你在 ViewController 中使用 TableViewController 而不是 TableView,你可以跳过这一步。
第 6 步:根据 Cell 类拖放单元格中的图像视图和标签。然后从情节提要提供到他们的插座的连接。
第 7 步:现在,在视图控制器中编写 UITableViewDatasource 所需的方法。
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "firstCustomCell")
//set the data here
return cell
}
else if indexPath.row == 1 {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "secondCustomCell")
//set the data here
return cell
}
else {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "thirdCustomCell")
//set the data here
return cell
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Swift 3.0 + 用最少的代码更新
基本概念:使用动态单元格原型创建表格视图。为每个单元原型分配标识符并创建自定义表格视图单元类。在表格视图的委托方法中启动并显示自定义单元格。
1. 在故事板上创建单元格
将 tableView 拖到您的视图控制器,向其中添加原型单元格,然后将 UI 元素拖放到您的表格视图单元格中,如果需要,请正确添加约束。
https://i.stack.imgur.com/0B9V1.gif
<强> 2。创建自定义 UITableViewCell
类
将以下代码添加到您的项目中。我把它放在视图控制器类的正上方。
class FirstTableCell: UITableViewCell {
}
class SecondTableCell: UITableViewCell {
}
class ThirdTableCell: UITableViewCell {
}
3. 为单元原型分配自定义类和标识符
对于情节提要中的每个单元原型,分配从第 2 步创建的自定义类,然后输入唯一标识符。
https://i.stack.imgur.com/yKFtJ.gif
4. 将 UI 元素连接到 swift 代码
控制拖动表视图并连接到视图控制器类。控制拖动步骤 1 中添加到单元格原型的 UI 元素,并连接到相应的表格视图单元格类。
https://i.stack.imgur.com/h22re.gif
5.添加代码到view controller,控制table view
使您的视图控制器符合表视图委托
class YourViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
在 viewDidLoad
中,设置表格视图的委托和数据源。
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.dataSource = self
self.tableView.delegate = self
}
最后,根据最低要求添加两个委托方法来控制您的表格视图。
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "firstTableCell") as! FirstTableCell
// Set up cell.label
return cell
} else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "secondTableCell") as! SecondTableCell
// Set up cell.button
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "thirdTableCell") as! ThirdTableCell
// Set up cell.textField
return cell
}
}
6. 试一试 :)
https://i.stack.imgur.com/HZTVw.gif
我建议使用这个简单易用的库,我为表格和集合视图制作。您可以根据需要添加任意类型的单元格,并在没有样板代码的情况下实现更干净的 ViewController。
https://github.com/deniskakacka/DKDataSources
对于第一张图片上的 UI,您在 ViewController 中的所有代码都是这样的:
lazy var dataSource = DKTableDataSource<CellType>(
models: [
DisclosureCellModel(title: "Disclosure 1", action: .action1),
TextFieldCellModel(title: "TextField 1", placeholder: "Placeholder 1"),
SwitchCellModel(title: "Switch 1", isOn: true),
BannerCellModel(imageName: "placeholder"),
SwitchCellModel(title: "Switch 2", isOn: false),
BannerCellModel(imageName: "placeholder"),
DisclosureCellModel(title: "Disclosure 2", action: .action2),
TextFieldCellModel(title: "TextField 2", placeholder: "Placeholder 2"),
BannerCellModel(imageName: "placeholder")
]
)
// in `viewDidLoad`
dataSource.registerCells(for: tableView)
tableView.dataSource = dataSource
https://i.stack.imgur.com/Gcwfr.jpg
斯威夫特 5
创建 3 个自定义 TableViewCells。我将它命名为 FirstTableViewCell、SecondTableViewCell、ThirdTableViewCell
https://i.stack.imgur.com/EbiYo.png
添加所有 3 个自定义单元类并根据需要添加插座。我在下面的代码中添加了。类 FirstTableViewCell: UITableViewCell { @IBOutlet 弱 var myImageView: UIImageView! @IBOutlet 弱变量 myLabel:UILabel! static let cellIdentifier = "FirstTableViewCell" static let cellNib = UINib(nibName: "FirstTableViewCell", bundle: Bundle.main) override func awakeFromNib() { super.awakeFromNib() // 初始化代码 } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // 配置选中状态的视图 } }
3:在您的 ViewController 中,为您的 TableView 创建一个 Outlet。此外,您需要在类定义中添加 UITableViewDelegate 和 UITableViewDataSource。
@IBOutlet weak var tableView: UITableView! {
didSet {
tableView.delegate = self
tableView.dataSource = self
tableView.register(FirstTableViewCell.cellNib, forCellReuseIdentifier: FirstTableViewCell.cellIdentifier)
tableView.register(SecondTableViewCell.cellNib, forCellReuseIdentifier: SecondTableViewCell.cellIdentifier)
tableView.register(ThirdTableViewCell.cellNib, forCellReuseIdentifier: ThirdTableViewCell.cellIdentifier)
}
}
4.现在,在视图控制器中编写 UITableViewDatasource 所需的方法。
extension ViewController: UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
guard let cell = tableView.dequeueReusableCell(withIdentifier: FirstTableViewCell.cellIdentifier, for: indexPath) as? FirstTableViewCell else { return UITableViewCell() }
return cell
}else if indexPath.row == 1 {
guard let cell = tableView.dequeueReusableCell(withIdentifier: SecondTableViewCell.cellIdentifier, for: indexPath) as? SecondTableViewCell else { return UITableViewCell() }
return cell
}else {
guard let cell = tableView.dequeueReusableCell(withIdentifier: ThirdTableViewCell.cellIdentifier, for: indexPath) as? ThirdTableViewCell else { return UITableViewCell() }
return cell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50 //According requirement
}
}
您的代码将如下所示(查看控制器代码)
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView! {
didSet {
tableView.delegate = self
tableView.dataSource = self
tableView.register(FirstTableViewCell.cellNib, forCellReuseIdentifier: FirstTableViewCell.cellIdentifier)
tableView.register(SecondTableViewCell.cellNib, forCellReuseIdentifier: SecondTableViewCell.cellIdentifier)
tableView.register(ThirdTableViewCell.cellNib, forCellReuseIdentifier: ThirdTableViewCell.cellIdentifier)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
extension ViewController: UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
guard let cell = tableView.dequeueReusableCell(withIdentifier: FirstTableViewCell.cellIdentifier, for: indexPath) as? FirstTableViewCell else { return UITableViewCell() }
return cell
}else if indexPath.row == 1 {
guard let cell = tableView.dequeueReusableCell(withIdentifier: SecondTableViewCell.cellIdentifier, for: indexPath) as? SecondTableViewCell else { return UITableViewCell() }
return cell
}else {
guard let cell = tableView.dequeueReusableCell(withIdentifier: ThirdTableViewCell.cellIdentifier, for: indexPath) as? ThirdTableViewCell else { return UITableViewCell() }
return cell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50 //According requirement
}
}
上面的答案是最好的答案,但是有很多理由可以解决这个问题。对于有此问题的任何人,这是另一个潜在的解决方案:
我的问题是我正在使用 ViewController 类而不是情节提要视图。所以我对故事板单元格的引用是没有意义的,因为故事板没有被使用。
我正在这样做:
let viewControllerB = SubViewController()
viewControllerB.passedData = diseases[indexPath.row].name
navigationController?.pushViewController(viewControllerB, animated: true)
我需要做这样的事情:
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "SubViewStoryboardController") as! SubViewController
nextViewController.passedData = diseases[indexPath.row].name
self.present(nextViewController, animated:true, completion:nil)
希望这可以帮助某人。
如果您使用自定义 XIB 作为 TableView 单元格,请遵循以下代码
//Write in viewDidLoad()
let nib = UINib(nibName: "PrinterTVC", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "CELL1")
let nib1 = UINib(nibName: "SelectAndEditTVC", bundle: nil)
tableView.register(nib1, forCellReuseIdentifier: "CELL2")
UITableViewController
正在继承已具有 UITableviewDataSource
的 UIViewController
& UITableviewDelegate
映射到自身。
您可以继承 UITableViewController
或在 ViewController
中使用 TableView
。之后,您必须实现在 UITableviewDataSource
中声明的所需方法(cellForRowAtIndexPath
and numberOfRowsInSection
)。
同样在情节提要中,您需要创建具有唯一 ID 的单元原型。
有基本类型的单元格,带有(例如标题,副标题) - 如果您不需要特殊配置,也可以使用它们。
因此,对于选择器,是的,您需要创建自己的自定义单元格。创建必要的自定义 UITableViewCell
类保存日期选择器,并确保使用委托将所需结果发送回您的 ViewController
。