Ios 使用Swift以编程方式自定义UITableViewCell

Ios 使用Swift以编程方式自定义UITableViewCell,ios,uitableview,swift,custom-controls,Ios,Uitableview,Swift,Custom Controls,嘿,我正在尝试创建一个自定义的UITableViewCell,但在模拟器上什么也看不到。你能帮帮我吗 只有当Ivar labUserName=UILabel(frame:CGRectMake(0.0,0.0,130,30))时,我才能看到标签 但它与细胞重叠。我不明白,自动布局应该知道每个单元格的首选大小/最小大小 谢谢 import Foundation import UIKit class TableCellMessages: UITableViewCell { var imgUs

嘿,我正在尝试创建一个自定义的
UITableViewCell
,但在模拟器上什么也看不到。你能帮帮我吗

只有当I
var labUserName=UILabel(frame:CGRectMake(0.0,0.0,130,30))时,我才能看到标签

但它与细胞重叠。我不明白,自动布局应该知道每个单元格的首选大小/最小大小

谢谢

import Foundation
import UIKit

class TableCellMessages: UITableViewCell {
    var imgUser     = UIImageView();
    var labUserName = UILabel();
    var labMessage  = UILabel();
    var labTime     = UILabel();


    override init(style: UITableViewCellStyle, reuseIdentifier: String) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        imgUser.layer.cornerRadius = imgUser.frame.size.width / 2;
        imgUser.clipsToBounds = true;



        contentView.addSubview(imgUser)
        contentView.addSubview(labUserName)
        contentView.addSubview(labMessage)
        contentView.addSubview(labTime)


        //Set layout
        var viewsDict = Dictionary <String, UIView>()
        viewsDict["image"] = imgUser;
        viewsDict["username"] = labUserName;
        viewsDict["message"] = labMessage;
        viewsDict["time"] = labTime;
        //Image

        //contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[image(100)]-'", options: nil, metrics: nil, views: viewsDict));
        //contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[image(100)]-|", options: nil, metrics: nil, views: viewsDict));
         contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[username]-[message]-|", options: nil, metrics: nil, views: viewsDict));
         contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[username]-|", options: nil, metrics: nil, views: viewsDict));
          contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[message]-|", options: nil, metrics: nil, views: viewsDict));

    }

    required init(coder aDecoder: NSCoder) {
         fatalError("init(coder:) has not been implemented")
    }

}
<代码>导入基础 导入UIKit 类TableCellMessages:UITableViewCell{ var imgUser=UIImageView(); var labUserName=UILabel(); var labMessage=UILabel(); var labTime=UILabel(); 重写初始化(样式:UITableViewCellStyle,reuseIdentifier:String){ init(样式:style,reuseIdentifier:reuseIdentifier) imgUser.layer.cornerRadius=imgUser.frame.size.width/2; imgUser.clipsToBounds=true; contentView.addSubview(imgUser) contentView.addSubview(labUserName) contentView.addSubview(labMessage) contentView.addSubview(labTime) //集合布局 var viewsDict=字典() viewsDict[“图像”]=imgUser; viewsDict[“用户名”]=labUserName; viewsDict[“消息”]=labMessage; viewsDict[“时间”]=labTime; //形象 //contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(“H:|-[image(100)]-”,选项:无,度量:无,视图:viewsDict)); //contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(“V:|-[image(100)]-|”,选项:无,度量:无,视图:viewsDict)); contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(“V:|-[username]-[message]-|”,选项:nil,度量:nil,视图:viewsDict)); contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(“H:|-[username]-|”,选项:nil,度量:nil,视图:viewsDict)); contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(“H:|-[message]-|”,选项:nil,度量:nil,视图:viewsDict)); } 必需的初始化(编码器aDecoder:NSCoder){ fatalError(“初始化(编码者:)尚未实现”) } }
让我们做一些假设:

您有一个iOS8项目,其中包含一个
UITableViewController
。它的
tableView
有一个独特的原型
UITableViewCell
,带有自定义样式和标识符:“cell”

UITableViewController
将链接到Class
TableViewController
单元格
将链接到Class
CustomTableViewCell

然后,您将能够设置以下代码(针对Swift 2更新):

CustomTableViewCell.swift:

import Foundation
import UIKit

class CustomTableViewCell: UITableViewCell {

    let imgUser = UIImageView()
    let labUerName = UILabel()
    let labMessage = UILabel()
    let labTime = UILabel()

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        imgUser.backgroundColor = UIColor.blue

        imgUser.translatesAutoresizingMaskIntoConstraints = false
        labUerName.translatesAutoresizingMaskIntoConstraints = false
        labMessage.translatesAutoresizingMaskIntoConstraints = false
        labTime.translatesAutoresizingMaskIntoConstraints = false

        contentView.addSubview(imgUser)
        contentView.addSubview(labUerName)
        contentView.addSubview(labMessage)
        contentView.addSubview(labTime)

        let viewsDict = [
            "image" : imgUser,
            "username" : labUerName,
            "message" : labMessage,
            "labTime" : labTime,
            ] as [String : Any]

        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[image(10)]", options: [], metrics: nil, views: viewsDict))
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[labTime]-|", options: [], metrics: nil, views: viewsDict))
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[username]-[message]-|", options: [], metrics: nil, views: viewsDict))
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[username]-[image(10)]-|", options: [], metrics: nil, views: viewsDict))
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[message]-[labTime]-|", options: [], metrics: nil, views: viewsDict))
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}
TableViewController.swift:


您将看到这样的显示(iPhone环境):

这是对回答Imanou Petit的swift 3的更新

CustomTableViewCell.swift:

import Foundation
import UIKit

class CustomTableViewCell: UITableViewCell {

    let imgUser = UIImageView()
    let labUerName = UILabel()
    let labMessage = UILabel()
    let labTime = UILabel()

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        imgUser.backgroundColor = UIColor.blue

        imgUser.translatesAutoresizingMaskIntoConstraints = false
        labUerName.translatesAutoresizingMaskIntoConstraints = false
        labMessage.translatesAutoresizingMaskIntoConstraints = false
        labTime.translatesAutoresizingMaskIntoConstraints = false

        contentView.addSubview(imgUser)
        contentView.addSubview(labUerName)
        contentView.addSubview(labMessage)
        contentView.addSubview(labTime)

        let viewsDict = [
            "image" : imgUser,
            "username" : labUerName,
            "message" : labMessage,
            "labTime" : labTime,
            ] as [String : Any]

        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[image(10)]", options: [], metrics: nil, views: viewsDict))
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[labTime]-|", options: [], metrics: nil, views: viewsDict))
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[username]-[message]-|", options: [], metrics: nil, views: viewsDict))
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[username]-[image(10)]-|", options: [], metrics: nil, views: viewsDict))
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[message]-[labTime]-|", options: [], metrics: nil, views: viewsDict))
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}
Settigns.swift:

import Foundation
import UIKit


class Settings: UIViewController, UITableViewDelegate, UITableViewDataSource {

    private var myTableView: UITableView!

    private let sections: NSArray = ["fruit", "vegitable"]    //Profile    network    audio Codecs
    private let fruit: NSArray = ["apple", "orange", "banana", "strawberry", "lemon"]
    private let vegitable: NSArray = ["carrots", "avocado", "potato", "onion"]



    override func viewDidLoad() {
        super.viewDidLoad()

        // get width and height of View
        let barHeight: CGFloat = UIApplication.shared.statusBarFrame.size.height
        let navigationBarHeight: CGFloat = self.navigationController!.navigationBar.frame.size.height
        let displayWidth: CGFloat = self.view.frame.width
        let displayHeight: CGFloat = self.view.frame.height

        myTableView = UITableView(frame: CGRect(x: 0, y: barHeight+navigationBarHeight, width: displayWidth, height: displayHeight - (barHeight+navigationBarHeight)))
        myTableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "cell")         // register cell name

        myTableView.dataSource = self
        myTableView.delegate = self

        //Auto-set the UITableViewCells height (requires iOS8+)
        myTableView.rowHeight = UITableViewAutomaticDimension
        myTableView.estimatedRowHeight = 44

        self.view.addSubview(myTableView)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }


    // return the number of sections
    func numberOfSections(in tableView: UITableView) -> Int{
        return sections.count
    }



    // return the title of sections
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sections[section] as? String
    }


    // called when the cell is selected.
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        print("Num: \(indexPath.row)")
        if indexPath.section == 0 {
            print("Value: \(fruit[indexPath.row])")
        } else if indexPath.section == 1 {
            print("Value: \(vegitable[indexPath.row])")
        }
    }

    // return the number of cells each section.
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if section == 0 {
            return fruit.count
        } else if section == 1 {
            return vegitable.count
        } else {
            return 0
        }
    }

    // return cells
    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell

        if indexPath.section == 0 {
            cell.labUerName.text = "\(fruit[indexPath.row])"
            cell.labMessage.text = "Message \(indexPath.row)"
            cell.labTime.text = DateFormatter.localizedString(from: NSDate() as Date, dateStyle: .short, timeStyle: .short)
        } else if indexPath.section == 1 {
            cell.labUerName.text = "\(vegitable[indexPath.row])"
            cell.labMessage.text = "Message \(indexPath.row)"
            cell.labTime.text = DateFormatter.localizedString(from: NSDate() as Date, dateStyle: .short, timeStyle: .short)
        }



        return cell
    }

}
在Swift 5中

自定义UITableViewCell:

import UIKit

class CourseCell: UITableViewCell {

    let courseName = UILabel()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        // Set any attributes of your UI components here.
        courseName.translatesAutoresizingMaskIntoConstraints = false
        courseName.font = UIFont.systemFont(ofSize: 20)
        
        // Add the UI components
        contentView.addSubview(courseName)
        
        NSLayoutConstraint.activate([
            courseName.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            courseName.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20),
            courseName.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
            courseName.heightAnchor.constraint(equalToConstant: 50)
        ])
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
UITableViewController:

import UIKit

class CourseTableViewController: UITableViewController {

    private var data: [Int] = [1]
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // You must register the cell with a reuse identifier
        tableView.register(CourseCell.self, forCellReuseIdentifier: "courseCell")
        // Change the row height if you want
        tableView.rowHeight = 150
        // This will remove any empty cells that are below your data filled cells
        tableView.tableFooterView = UIView()
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {

        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        return data.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "courseCell", for: indexPath) as! CourseCell
        cell.courseName.text = "Course name"

        return cell
    }
 
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

如果在单元格中看到重叠图像,则单元格高度可能未正确设置。请看:我只在使用CGRectMake时看到重叠,但我不想使用CGRectMake,我想自动,我想自动布局来控制大小,这是我不明白的一件事。请帮忙,里面的标签应该有自己的大小吗?没有我必须告诉他们大小是多少?我知道这条线很旧,对于我来说,当对所有UI元素(如labels、views等)执行“TranslatesAutoResizezingMaskintoConstraints=false”时,约束效果更好。在您给它诸如cell.labUerName.text=“Name”之类的参数之前,这段代码首先调用awakefromnib,而不是将变量传递到cell类中。由于这个原因,我遇到了一个崩溃,应该怎么做?要删除对Interface Builder注册forCellReuseIdentifier的依赖,请在loadView()或ViewDidLoad()中将以下行添加到UITableViewController中:
tableView.register(CustomTableViewCell.classForCoder(),forCellReuseIdentifier:“cell”)
。只是想知道。。。为什么您决定使用
init(style:)
而不是
awakeFromNib()
哪个Imanou-Petit使用?有区别吗?Imanou Petit假设用户使用的是Interface Builder。当我使用他的答案时,我使代码完全独立于任何故事板/xib=nib,因此在我的应用程序中,永远不会调用awakeFromNib()。顺便说一句,我还必须添加这一行:myTableView.register(CustomTableViewCell.self,forCellReuseIdentifier:“cell”)嘿@Tiagmendes快速提问,我使用故事板创建了一个自定义单元格,我试图通过插座在CellForRowatineXpath方法中更改其背景颜色,但它似乎不起作用。像.ishiden这样的属性可以很好地工作。这是正确的做法吗?我遗漏了什么吗?这是我在Swift5中的修复方法
import UIKit

class CourseTableViewController: UITableViewController {

    private var data: [Int] = [1]
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // You must register the cell with a reuse identifier
        tableView.register(CourseCell.self, forCellReuseIdentifier: "courseCell")
        // Change the row height if you want
        tableView.rowHeight = 150
        // This will remove any empty cells that are below your data filled cells
        tableView.tableFooterView = UIView()
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {

        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        return data.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "courseCell", for: indexPath) as! CourseCell
        cell.courseName.text = "Course name"

        return cell
    }
 
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
    }
}