UINavigationView弹出到根视图控制器问题

时间:2019-06-11 15:08:46

标签: ios swift core-data uinavigationcontroller

我的应用程序中有两个视图控制器。在第一个视图中,我显示核心数据对象。我有带有UILabel的自定义UIView来做到这一点。在第二个视图中,我有操作来添加新的核心数据对象。两者都嵌入UINavigationController中,其中第一个视图是根视图控制器。添加对象时,我想使用户回到根视图,但是它必须包含新数据。

我试图使用.popToRootViewController()操作,但是当我返回时,我的数据没有更新。我拥有与启动应用程序时相同的数据。

SecondViewController中的代码

  private func saveCaffeineData(coffeeName: String, coffeeSelectedSize: String, coffeeCaffeineAmount: Double, coffeeshop: String, date: Date) {
        guard let appDelegate =
            UIApplication.shared.delegate as? AppDelegate else {
                return
        }

        let managedContext = appDelegate.persistentContainer.viewContext

        let entity = NSEntityDescription.entity(forEntityName: "CaffeineData", in: managedContext)!
        let caffeineData = NSManagedObject(entity: entity, insertInto: managedContext)

        caffeineData.setValuesForKeys(["coffeeName" : coffeeName, "coffeeSize" : coffeeSelectedSize, "caffeineAmount" : coffeeCaffeineAmount, "coffeeShop" : coffeeshop, "date" : date])

        do {
        try managedContext.save()
            allCaffeineData.append(caffeineData)

            navigationController?.popToRootViewController(animated: true)
        } catch let error as NSError {
            print("Could not save. \(error), \(error.userInfo)")
        }
    }

FirstViewController中的代码

lazy var todaySummaryView: TodaySummaryView = {
        let todaySummaryView = TodaySummaryView(todayCoffeeAmount: countTodayCaffeineAmount(), caffeineState: getCaffeineUserState()!)
        todaySummaryView.translatesAutoresizingMaskIntoConstraints = false
        todaySummaryView.backgroundColor = .white
        todaySummaryView.layer.cornerRadius = 10
        return todaySummaryView
    }()

    private func setupLayout() {
        title = "Dashboard"

        if caffeineData.count == 0 {
            view.addSubview(nothingView)
            view.addSubview(addDataButton)

            addDataButton.addTarget(self, action: #selector(addCaffeine), for: .touchUpInside)

            NSLayoutConstraint.activate([
                nothingView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
                nothingView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
                nothingView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
                nothingView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
                addDataButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
                addDataButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20),
                addDataButton.heightAnchor.constraint(equalToConstant: 50),
                addDataButton.widthAnchor.constraint(equalToConstant: 300)
            ])
        } else {
            view.addSubview(dashboardScrollView)
            view.addSubview(addDataButton)

            addDataButton.addTarget(self, action: #selector(addCaffeine), for: .touchUpInside)

            dashboardScrollView.addSubview(dashboardScrollViewContentView)
            dashboardScrollViewContentView.addSubview(todaySummaryView)

            NSLayoutConstraint.activate([
                dashboardScrollView.topAnchor.constraint(equalTo: view.topAnchor),
                dashboardScrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                dashboardScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
                dashboardScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),

                dashboardScrollViewContentView.topAnchor.constraint(equalTo: dashboardScrollView.topAnchor),
                dashboardScrollViewContentView.leadingAnchor.constraint(equalTo: dashboardScrollView.leadingAnchor),
                dashboardScrollViewContentView.trailingAnchor.constraint(equalTo: dashboardScrollView.trailingAnchor),
                dashboardScrollViewContentView.bottomAnchor.constraint(equalTo: dashboardScrollView.bottomAnchor),
                dashboardScrollViewContentView.centerXAnchor.constraint(equalTo: dashboardScrollView.centerXAnchor),

                todaySummaryView.topAnchor.constraint(equalTo: dashboardScrollViewContentView.topAnchor, constant: 20),
                todaySummaryView.centerXAnchor.constraint(equalTo: dashboardScrollViewContentView.centerXAnchor),
                todaySummaryView.leadingAnchor.constraint(equalTo: dashboardScrollViewContentView.leadingAnchor, constant: 15),
                todaySummaryView.trailingAnchor.constraint(equalTo: dashboardScrollViewContentView.trailingAnchor, constant: -15),

                addDataButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
                addDataButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20),
                addDataButton.heightAnchor.constraint(equalToConstant: 50),
                addDataButton.widthAnchor.constraint(equalToConstant: 300)
            ])
        }
    }

    @objc private func addCaffeine() {
        let destinationViewController = SelectCoffeeTableViewController()

        navigationController?.pushViewController(destinationViewController, animated: true)
    }

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

    override func viewDidAppear(_ animated: Bool) {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
            return
        }

        let managedContext = appDelegate.persistentContainer.viewContext
        let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "CaffeineData")

        do {
            caffeineData = try managedContext.fetch(fetchRequest)
            setupLayout()
        } catch let error as NSError {
            print("Something goes wrong! \(error.description)")
        }
    }

    private func countTodayCaffeineAmount() -> Float {
        var caffeineAmount = Float()

        let calendar = Calendar.current

        let todayDate = Date()
        let todayDay = calendar.component(.day, from: todayDate)
        let todayMonth = calendar.component(.month, from: todayDate)
        let todayYear = calendar.component(.year, from: todayDate)

        for caffeineRow in caffeineData {
            let caffeineDay = calendar.component(.day, from: caffeineRow.value(forKey: "date") as! Date)
            let caffeineMonth = calendar.component(.month, from: caffeineRow.value(forKey: "date") as! Date)
            let caffeineYear = calendar.component(.year, from: caffeineRow.value(forKey: "date") as! Date)

            if (todayDay == caffeineDay && todayMonth == caffeineMonth && todayYear == caffeineYear) {
                caffeineAmount += caffeineRow.value(forKey: "caffeineAmount") as! Float
            }
        }
        return caffeineAmount
    }

    private func getCaffeineUserState() -> CaffeineState? {
        var caffeineState: CaffeineState

        let caffeineAmount = countTodayCaffeineAmount()

        switch caffeineAmount {
        case 0..<200:
            caffeineState = .normal
        case 200..<300:
            caffeineState = .warning
        case 300...:
            caffeineState = .dangerous
        default:
            return nil
        }

        return caffeineState

CustomView中的代码

//
//  TodaySummaryView.swift
//  Caffeinee
//
//  Created by Piotr Sirek on 11/06/2019.
//  Copyright © 2019 Piotr Sirek. All rights reserved.
//

import UIKit

class TodaySummaryView: UIView {
    var todayCoffeeAmount: Float = 0.0
    var caffeineState: CaffeineState = CaffeineState.normal

    lazy var todayLabel: UILabel = {
        let todayLabel = UILabel()
        todayLabel.font = UIFont.systemFont(ofSize: 16, weight: .bold)
        todayLabel.text = "Today"
        todayLabel.textColor = .white
        todayLabel.textAlignment = .center
        todayLabel.translatesAutoresizingMaskIntoConstraints = false
        return todayLabel
    }()

    lazy var todayLabelView: UIView = {
        let todayLabelView = UIView(frame: CGRect(x: 0, y: 0, width: 74, height: 28))
        todayLabelView.layer.cornerRadius = 5
        todayLabelView.translatesAutoresizingMaskIntoConstraints = false
        return todayLabelView
    }()

    lazy var todayStateLabel: UILabel = {
        let todayStateLabel = UILabel()
        todayStateLabel.font = UIFont.systemFont(ofSize: 16, weight: .semibold)
        todayStateLabel.textColor = .black
        todayStateLabel.textAlignment = .left
        todayStateLabel.translatesAutoresizingMaskIntoConstraints = false
        todayStateLabel.numberOfLines = 0
        return todayStateLabel
    }()

    lazy var caffeineAmountLabel: UILabel = {
        let caffeineAmountLabel = UILabel()
        caffeineAmountLabel.font = UIFont.systemFont(ofSize: 45, weight: .heavy)
        caffeineAmountLabel.textAlignment = .left
        caffeineAmountLabel.translatesAutoresizingMaskIntoConstraints = false
        caffeineAmountLabel.text = "142"
        return caffeineAmountLabel
    }()

    lazy var caffeineUnitLabel: UILabel = {
        let caffeineUnitLabel = UILabel()
        caffeineUnitLabel.font = UIFont.systemFont(ofSize: 18, weight: .heavy)
        caffeineUnitLabel.textAlignment = .left
        caffeineUnitLabel.translatesAutoresizingMaskIntoConstraints = false
        caffeineUnitLabel.text = "mg"
        return caffeineUnitLabel
    }()

    private func setupView() {
        self.addSubview(todayLabelView)
        self.addSubview(todayStateLabel)
        self.addSubview(caffeineAmountLabel)
        self.addSubview(caffeineUnitLabel)

        todayLabelView.addSubview(todayLabel)

        NSLayoutConstraint.activate([
            todayLabelView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: 15),
            todayLabelView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor, constant: 15),
            todayLabelView.heightAnchor.constraint(equalToConstant: 28),
            todayLabelView.widthAnchor.constraint(equalToConstant: 74),

            todayLabel.centerXAnchor.constraint(equalTo: todayLabelView.centerXAnchor),
            todayLabel.centerYAnchor.constraint(equalTo: todayLabelView.centerYAnchor),
            todayLabel.heightAnchor.constraint(equalToConstant: 26),
            todayLabel.widthAnchor.constraint(equalToConstant: 70),

            todayStateLabel.topAnchor.constraint(equalTo: todayLabelView.bottomAnchor, constant: 20),
            todayStateLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor, constant: 15),
            todayStateLabel.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor, constant: -15),
            todayStateLabel.centerXAnchor.constraint(equalTo: layoutMarginsGuide.centerXAnchor),

            caffeineAmountLabel.topAnchor.constraint(equalTo: todayStateLabel.bottomAnchor, constant: 15),
            caffeineAmountLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor, constant: 15),
            caffeineAmountLabel.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor, constant: -15),

            caffeineUnitLabel.leadingAnchor.constraint(equalTo: caffeineAmountLabel.trailingAnchor, constant: 0),
            caffeineUnitLabel.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor, constant: -20)
        ])
    }

    private func presentState(todayCoffeeAmount: Float, caffeineState: CaffeineState) {
        caffeineAmountLabel.text = "\(todayCoffeeAmount)"

        switch caffeineState {
        case .normal:
            todayLabelView.backgroundColor = UIColor(red:0.24, green:0.63, blue:0.98, alpha:1.0)
            todayStateLabel.text = "Your caffeine level is quiet good today. Keep it up!"
        case .warning:
            todayLabelView.backgroundColor = UIColor(red:0.96, green:0.68, blue:0.42, alpha:1.0)
            todayStateLabel.text = "Your caffeine now is near your daily limit. Be carefull!"
        case .dangerous:
            todayLabelView.backgroundColor = UIColor(red:1.00, green:0.31, blue:0.31, alpha:1.0)
            todayStateLabel.text = "Your caffeine level is over your daily limit. Don’t drink any coffee for rest of the day."
        }
    }

    override class var requiresConstraintBasedLayout: Bool {
        return true
    }

    override var intrinsicContentSize: CGSize {
        return CGSize(width: 340, height: 200)
    }

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

    init(todayCoffeeAmount: Float, caffeineState: CaffeineState) {
        super.init(frame: CGRect())
        setupView()
        presentState(todayCoffeeAmount: todayCoffeeAmount, caffeineState: caffeineState)
    }

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

1 个答案:

答案 0 :(得分:0)

您需要实现委托协议,或使用通知来更新第一个控制器。 这是一个如何使用委托的示例:

protocol SecondViewControllerDelegate: class {
    func caffeineDataSaved(controller: SecondViewController)
}

class SecondViewController: UIViewController {
   weak var delegate: SecondViewControllerDelegate?

   private func saveCaffeineData(coffeeName: String, coffeeSelectedSize: String, coffeeCaffeineAmount: Double, coffeeshop: String, date: Date) {
        guard let appDelegate =
            UIApplication.shared.delegate as? AppDelegate else {
                return
        }

        let managedContext = appDelegate.persistentContainer.viewContext

        let entity = NSEntityDescription.entity(forEntityName: "CaffeineData", in: managedContext)!
        let caffeineData = NSManagedObject(entity: entity, insertInto: managedContext)

        caffeineData.setValuesForKeys(["coffeeName" : coffeeName, "coffeeSize" : coffeeSelectedSize, "caffeineAmount" : coffeeCaffeineAmount, "coffeeShop" : coffeeshop, "date" : date])

        do {
        try managedContext.save()
            allCaffeineData.append(caffeineData)
            self.delegate?.caffeineDataSaved(controller: self)

            navigationController?.popToRootViewController(animated: true)
        } catch let error as NSError {
            print("Could not save. \(error), \(error.userInfo)")
        }
    }
}

首先,在FirstViewController类中,将FirstViewController声明为SecondViewController的委托。您可以在ViewDidLoad或实例化SecondViewController的任何地方执行此操作:

self.secondController.delegate = self

现在,在FirstViewController中,您需要实现委托方法:

 func caffeineDataSaved(controller: SecondViewController) {
    //Update your view.
}