ios - UITableViewCell 忽略自动布局

标签 ios swift uitableview autolayout

几天以来我尝试了所有方法,即使我尝试使用自动维度,并且估计行高度 = 44,但都没有运气。我是 UITableView 的新手,我试图用它来练习。我在stackoverflow等中到处寻找,但没有运气。我不确定我在下面的代码中做错了什么。

在 View Controller 中:

reminder_tableview.frame = view.bounds
reminder_tableview.allowsSelection = false
reminder_tableview.estimatedRowHeight = 44
reminder_tableview.rowHeight = UITableView.automaticDimension
reminder_tableview.register(reminder_tableCell.self, forCellReuseIdentifier: "reminderList")
reminder_tableview.delegate = self
reminder_tableview.dataSource = self
tab2_body.addSubview(reminder_tableview)

在 UITableViewDelegate 的扩展中,UITableViewDataSource:
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {return UITableView.automaticDimension}
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {return 50.0}
    func numberOfSections(in tableView: UITableView) -> Int {return reminder_category_user.count}
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        if reminder_tableisready == true {
            let category_name = UILabel()
            category_name.frame = CGRect(x: 20, y: 0, width: view.frame.width - 80, height: 50)
            category_name.font = UIFont(name: "Arial", size: 30)
            category_name.text = reminder_category_user[section]
            category_name.textColor = UIColor.red

            let num_of_reminder = UILabel()
            num_of_reminder.frame = CGRect(x: view.frame.width - 75, y: 0, width: 70, height: 50)
            num_of_reminder.font = UIFont(name: "Arial", size: 30)
            num_of_reminder.text = String(reminder_final_table[section].count)
            num_of_reminder.textAlignment = .right
            num_of_reminder.textColor = UIColor.red

            let headerView = UIView()
            headerView.addSubview(category_name)
            headerView.addSubview(num_of_reminder)
            return headerView
        } else {
            return UIView()
        }
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if reminder_tableisready == true {
            return reminder_final_table[section].count
        } else {
            return 0
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reminderList") as! reminder_tableCell
        cell.backgroundColor = UIColor(red: 15/255, green: 15/255, blue: 15/255, alpha: 1)
        cell.frame.size.height = 100
        cell.textLabel?.text = reminder_final_table[indexPath.section][indexPath.row].pre_title
        cell.textLabel?.font = UIFont(name: "Arial", size: 18)
        cell.textLabel?.numberOfLines = 0
        cell.textLabel?.lineBreakMode = .byWordWrapping
        cell.textLabel?.sizeToFit()

        let getdatefromdatedue = Date(timeIntervalSince1970: TimeInterval(reminder_final_table[indexPath.section][indexPath.row].pre_datedue))
        let duedateformat = DateFormatter()
        duedateformat.dateFormat = "MMMM d, yyyy\nh:mm a"

        if reminder_final_table[indexPath.section][indexPath.row].pre_datedue != 0 {
            cell.layoutMargins.right = 160
            cell.reminder_date_due.text = "Date Due\n\(duedateformat.string(from: getdatefromdatedue))"
        } else {
            cell.reminder_date_due.text = ""
        }
        cell.reminder_date_due.textColor = UIColor.red
        cell.reminder_date_due.textAlignment = .right
        cell.reminder_date_due.numberOfLines = 4
        cell.reminder_date_due.font = UIFont(name: "Arial", size: 15)

        return cell
    }
}

class reminder_tableCell: UITableViewCell {
    var reminder_date_due = UILabel()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
        reminder_date_due.frame = CGRect(x: reminder_tableview.frame.width - 155, y: 0, width: 150, height: 66)
        addSubview(reminder_date_due)
    }
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

最佳答案

首先我会高度建议不要使用魔法值 对于您的框架(以及一般情况下),因为如果您想支持所有屏幕尺寸,它将很快失控。

此外,由于您预先计算了所有帧,因此您实际上没有使用自动布局。

苹果推出了Auto Layout具有基于约束的行为,因此您不必为每个屏幕尺寸手动完成所有帧计算工作。 Auto Layout将根据您设置的约束/ anchor 动态计算所有 View 的大小和位置,无论是使用 Storyboard 还是以编程方式。

我还在您的代码中看到您正在使用 reminder_tableview变量指的是你的UITableView并让我认为您将表格 View 用作全局属性:您应该不惜一切代价避免这种情况。

对于命名属性或方法,最佳实践是使用 Camel Case,因为它将使您的代码更易于阅读和理解 . Camel Case 是当您以小写字母开头名称时,然后将第二个和所有后续单词的第一个字母大写,例如:

let reminderTableIsReady = false
var reminderDueDateLabel: UILabel?
func scheduleNewReminder() {}
// ...

命名类、枚举或结构的常用方法是 上驼色案例 :
class ReminderTableViewCell: UITableViewCell {}

现在回到您的代码,我重构并制作了它的最小版本供您查看它如何与自动布局和约束一起工作,对于 UITableViewUITableViewCell .

我没有从您的代码中添加所有内容,但我认为您可以轻松地自己完成其余的工作:

提醒 View Controller :
import UIKit

// You don't have to use this Date extension below, but this will improve the performances by keeping only one formatter instance, since you will be reusing it in all your UITableViewCell:
extension Date {

    static let formatter = DateFormatter()

    func formatted() -> String {
        Date.formatter.dateFormat = "MMMM d, yyyy, hh:mm a"
        return Date.formatter.string(from: self)
    }
}

struct Reminder {
    let dueDate: TimeInterval
}

class ReminderViewController: UIViewController {

    private let reuseIdentifier = "reuseIdentifier"
    private var reminders = [[Reminder]]()
    private let tableView = UITableView(frame: .zero, style: .grouped)

    override func viewDidLoad() {
        super.viewDidLoad()
        setupViews()
        setupConstraints()
    }

    func setupViews() {
        tableView.delegate = self
        tableView.dataSource = self
        tableView.register(ReminderTableViewCell.self, forCellReuseIdentifier: reuseIdentifier)
        view.addSubview(tableView)
        reminders = // ... Set your data here
    }

    func setupConstraints() {
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
    }
}

extension ReminderViewController: UITableViewDelegate {

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        return nil
    }

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return CGFloat.leastNonzeroMagnitude
    }
}

extension ReminderViewController: UITableViewDataSource {

    func numberOfSections(in tableView: UITableView) -> Int {
        return reminders.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if section > reminders.count {
            return 0
        }
        return reminders[section].count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! ReminderTableViewCell
        let reminder = reminders[indexPath.section][indexPath.row]
        let date = Date(timeIntervalSince1970: reminder.dueDate)
        if reminder.dueDate > 0 {
            cell.dueDateLabel.text = "Due Date: \(date.formatted())"
        }
        return cell
    }
}

提醒 TableView 单元:
class ReminderTableViewCell: UITableViewCell {

    let dueDateLabel = UILabel()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupViews()
        setupConstraints()
    }

    func setupViews() {
        dueDateLabel.textColor = .red
        dueDateLabel.textAlignment = .right
        dueDateLabel.numberOfLines = 4
        dueDateLabel.font = UIFont(name: "Arial", size: 15)
        contentView.addSubview(dueDateLabel)
    }

    func setupConstraints() {
        dueDateLabel.translatesAutoresizingMaskIntoConstraints = false
        dueDateLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20).isActive = true
        dueDateLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20).isActive = true
        dueDateLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20).isActive = true
        dueDateLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20).isActive = true
    }

    required init?(coder: NSCoder) {
        fatalError()
    }
}

关于ios - UITableViewCell 忽略自动布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62208658/

相关文章:

ios - Xcode : Different behavior between swift Int and Objective-C int

swift - Enumerations 的枚举和避免使用 Any 类型

swift - 如何将图像保存到 iPhone 设备存储中/从 iPhone 设备存储中读取图像?

swift - 生成多页 PDF UIView

ios - 如何将 MKOverlay 对象存储到文件以便稍后检索

ios - Xamarin iOS Geolocator 后台服务在大约 30 分钟后死亡

ios - Swift 中的 ARC 在将属性分配为函数时如何解决强引用循环

swift - 如何同时缩放mapView和setCenterCoordinate?

当我固定导航栏重叠 TableView 时,iOS 7 看不到状态栏(信号、时间、电池)

ios - 根据 JSON 文件中的内容文本调整带有 UILabel 的自定义单元格的大小