ChatGPT解决这个技术问题 Extra ChatGPT

带有多个自定义单元格的 UITableview 与 Swift

我想使用具有不同自定义 tableViewCells 的 UITableview。我的 3 个细胞是这样的:

Cell1:应该有一个图像和一个标签。

Cell2:应该有两个标签。

Cell3:应该有一个dayPicker。

我不想为单元格编写标签。我如何在 Swift 中管理它。我必须为每个单元格编写自己的类吗?我可以使用一个 tableviewController 吗?如何在不同的单元格中填充数据?

我想生成一个tableView,就像iOS设备的联系人应用程序一样。


N
Natasha

让我先回答你的问题。

我必须为每个单元编写一个自己的类吗?=> 是的,我相信是的。至少,我会那样做。

我可以使用一个 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()
    }
}

我在 func cellForRowAtIndexPath 中收到消息:“无法将 'UITableViewCell' (0x1dfbfdc) 类型的值转换为 'Projekt.TitelTableViewCell' (0x89568)”。我正在使用 UITableViewController,并且我的自定义单元格“TitelZelle”有一个类“TitelTableViewCell”,我在“TitelZelle”单元格的身份检查器中设置了该类。我需要做什么?
我已将我的手机投射为! TitelTableViewCell 在此单元格中填充我的自定义 UI 元素。
试试这个=> 让 cell = tableView.dequeueReusableCellWithIdentifier("TitelZelle", forIndexPath: indexPath) as TitelTableViewCell
@PradipKumar,有什么问题?你的错误是什么?顺便说一句,如果你有任何疑问,你应该问一个问题。作者发布的评论应该有助于理解或澄清关于特定问题的这一点。如果你有问题,你应该去提问并开始你自己的帖子。
numberOfRowsInSection 帮助 tableview 确定我们想要多少行。因此,您应该只提供有助于方法确定行数的子句。 indexpath.row == 0 表示您已经有一行,但当时您的表不知道它是否有一行。所以,你应该这样做。
F
Fangming

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


极好的!我喜欢你的动画。
你能告诉我,是否可以为每个单元格添加一个标题?如果是这样,如何?
@PruthviHariharan 如果您想为每个或大部分单元格设置一个“标题”,那么实现标题单元格或部分标题并不是一个好主意,这需要更多代码来管理并且会影响性能。我的建议是在原型单元顶部放置一个视图,让它看起来像一个“标题”
@FangmingNing 你能用一个小例子解释一下吗?谢谢
如果您使用的是 UITableViewController 而不是 UIViewController,则不需要第 5 步。
D
Denis Kakačka

我建议使用这个简单易用的库,我为表格和集合视图制作。您可以根据需要添加任意类型的单元格,并在没有样板代码的情况下实现更干净的 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


P
Priyank Patel

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

C
Coltuxumab

上面的答案是最好的答案,但是有很多理由可以解决这个问题。对于有此问题的任何人,这是另一个潜在的解决方案:

我的问题是我正在使用 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)

希望这可以帮助某人。


t
thevikasnayak

如果您使用自定义 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")

m
milo526

UITableViewController 正在继承已具有 UITableviewDataSourceUIViewController & UITableviewDelegate 映射到自身。

您可以继承 UITableViewController 或在 ViewController 中使用 TableView。之后,您必须实现在 UITableviewDataSource 中声明的所需方法(cellForRowAtIndexPath and numberOfRowsInSection)。

同样在情节提要中,您需要创建具有唯一 ID 的单元原型。

有基本类型的单元格,带有(例如标题,副标题) - 如果您不需要特殊配置,也可以使用它们。

因此,对于选择器,是的,您需要创建自己的自定义单元格。创建必要的自定义 UITableViewCell 类保存日期选择器,并确保使用委托将所需结果发送回您的 ViewController


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅