如何修复未在UIStackView中显示的UITableView

时间:2019-09-17 16:59:50

标签: swift uitableview uistackview

我遵循了一个教程,该程序以编程方式(没有情节提要)构建了一个天气预报应用程序,以显示当前的城市和温度。我正在通过添加UITableView来修改它以显示5天的天气预报,而不只是当前的温度,但是它没有显示出来。

这是我的WeatherView代码:

class WeatherView: UIView, UITableViewDelegate, UITableViewDataSource {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

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

    private func setup() {
        setupViews()
        setupConstraints()
    }

    private func setupViews() {
        self.addSubview(mainStack)
        conditionsImageStack.addArrangedSubview(conditionsImageView)
        mainStack.addArrangedSubview(conditionsImageStack)


//        forecastTable.register(UITableView.self, forCellReuseIdentifier: "forecast")
        forecastTable.register(UITableViewCell.self, forCellReuseIdentifier: "forecast")
        forecastTable.delegate = self
        forecastTable.dataSource = self

        mainStack.addArrangedSubview(centerContentStack)
//        centerContentStack.addArrangedSubview(temperatureLabel)
        centerContentStack.addArrangedSubview(forecastTable)
        centerContentStack.addArrangedSubview(cityAndConditionsStack)

        cityAndConditionsStack.addArrangedSubview(cityLabel)
        cityAndConditionsStack.addArrangedSubview(conditionsLabel)

        mainStack.addArrangedSubview(buttonsStack)
        buttonsStack.addArrangedSubview(celsiusButton)
        buttonsStack.addArrangedSubview(fahrenheitButton)
        buttonsStack.addArrangedSubview(UIView(frame: .zero))
    }

    private func setupConstraints() {
        mainStack.pinEdges(to: self)
    }

    let mainStack: UIStackView = {
        let stackView = UIStackView(frame: .zero)
        stackView.axis = .vertical
        stackView.distribution = .equalSpacing
        stackView.spacing = 10
        stackView.isLayoutMarginsRelativeArrangement = true
        stackView.layoutMargins = UIEdgeInsets(top: 10, left: 30, bottom: 30, right: 30)
        return stackView
    }()

    let conditionsImageStack: UIStackView = {
        let stackView = UIStackView(frame: .zero)
        stackView.axis = .vertical
        stackView.distribution = .equalSpacing
        stackView.alignment = .trailing
        stackView.spacing = 10
        return stackView
    }()

    let cityAndConditionsStack: UIStackView = {
        let stackView = UIStackView(frame: .zero)
        stackView.axis = .vertical
        stackView.distribution = .fillProportionally
        stackView.spacing = 10
        return stackView
    }()

    let centerContentStack: UIStackView = {
        let stackView = UIStackView(frame: .zero)
        stackView.axis = .vertical
        stackView.distribution = .fillProportionally
        stackView.alignment = .center
        stackView.spacing = 60
        return stackView
    }()

    // TABLE CODE HERE

    var animalArray : [String] = ["elephant", "pig", "goat"]

    var forecastTable: UITableView = {
        let tableView = UITableView()
        let estimatedHeight = tableView.numberOfRows(inSection: 3) //You may need to modify as necessary
//        let width = parentView.frame.size.width
        let width = estimatedHeight
        tableView.frame = CGRect(x: 0, y: 0, width: width, height: estimatedHeight)

        return tableView
    }()

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = forecastTable.dequeueReusableCell(withIdentifier: "forecast")
        cell?.textLabel!.text = "Success"
        return cell!
    }

    let temperatureLabel: UILabel = {
        let label = UILabel(frame: .zero)
        label.font = UIFont.systemFont(ofSize: 144)
        label.textColor = .white
        label.textAlignment = .center
        label.text = "18°"
        return label
    }()

    let cityLabel: UILabel = {
        let label = UILabel(frame: .zero)
        label.font = UIFont.systemFont(ofSize: 36)
        label.textColor = .white
        label.textAlignment = .center
        label.text = "Atlanta"
        return label
    }()

    let conditionsLabel: UILabel = {
        let label = UILabel(frame: .zero)
        label.font = UIFont.systemFont(ofSize: 20)
        label.textColor = .white
        label.textAlignment = .center
        label.text = "Sunny"
        return label
    }()

    let conditionsImageView: UIImageView = {
        let image = UIImage(named: "sun")
        let imageView = UIImageView(image: image)
        imageView.contentMode = .scaleAspectFit
        imageView.widthAnchor.constraint(equalToConstant: image!.size.width).isActive = true
        imageView.heightAnchor.constraint(equalToConstant: image!.size.height).isActive = true
        return imageView
    }()

    let celsiusButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("°C", for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 73)
        button.setTitleColor(.white, for: .normal)
        return button
    }()

    let fahrenheitButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("°F", for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 73)
        button.setTitleColor(.white, for: .normal)
        return button
    }()

    let buttonsStack: UIStackView = {
        let stackView = UIStackView(frame: .zero)
        stackView.axis = .horizontal
        stackView.distribution = .equalCentering
        stackView.spacing = 10
        return stackView
    }()
}

这是我的ViewController代码:

class WeatherViewController: UIViewController {
    var mainView: WeatherView! { return self.view as! WeatherView }
    let presenter: WeatherPresenter!

    init(with presenter: WeatherPresenter){
        self.presenter = presenter
        super.init(nibName: nil, bundle: nil)
    }

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


    override func viewDidLoad() {
        super.viewDidLoad()
        updateBackground()
    }

    func updateBackground() {
        self.mainView.updateGradient(presenter.backgroundColor)
    }

    override func loadView() {
        self.view = WeatherView(frame: UIScreen.main.bounds)
    }
}

这是我的UIView +约束代码:

extension UIView {
    func pinEdges(to view: UIView){
        self.translatesAutoresizingMaskIntoConstraints = false
        self.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
        self.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        self.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        self.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    }
}

我尝试通过用tableView.frame = CGRect(x: 0, y: 0, width: width, height: estimatedHeight)设置尺寸来强制显示它,但这没用。

我将表注册到视图类中,而不是视图控制器类中,但是我不确定这是问题还是如何正确对其进行修改。

2 个答案:

答案 0 :(得分:1)

您做错了几件事...

首先,在var forecastTable: UITableView = {...}声明中,有一行:

let estimatedHeight = tableView.numberOfRows(inSection: 3)

但是,此时,表视图没有dataSource -即使有,您的dataSource也只有section. So the value returned is undefined. If I print(esttmatedHeight)I get 9223372036854775807 . So you are trying to set the frame of your table view to 9223372036854775807 x 9223372036854775807`

接下来,当您将表视图添加到堆栈视图时,堆栈视图将尝试根据堆栈视图的属性和表视图的固有大小来排列它。但是,此时表视图没有内部大小-您必须使用自动布局属性。

因此,请删除表格视图的框架设置,然后将其添加到堆栈视图中,然后使用:

    // I'm guessing you want a height based on number of rows * row height?
    // so, something like:
    let estimatedHeight = CGFloat(3 * 44)

    forecastTable.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        forecastTable.widthAnchor.constraint(equalTo: centerContentStack.widthAnchor),
        forecastTable.heightAnchor.constraint(equalToConstant: estimatedHeight),
        ])

这将使表格视图的宽度与保存表格的centerContentStack相同,并赋予其高度。

此时,您应该看到表格。

答案 1 :(得分:0)

您要将mainStack添加到superView中,但未指定其尺寸。您需要像这样设置对mainStack的约束,

mainStack.translatesAutoresizingMaskIntoConstraints = false
mainStack.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
mainStack.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
mainStack.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
mainStack.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true

以上代码用mainStack填充了整个超级视图。您可以根据需要修改此代码。