UINavigationView всплывает в корневом контроллере проблемы с представлением

У меня есть два контроллера представления в моем приложении. В первом представлении я отображаю основные объекты данных. У меня есть собственный UIView с UILabel для этого. Во втором представлении у меня есть действие по добавлению новых основных объектов данных. Оба встроены в 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")
    }
}

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам необходимо реализовать протокол делегата или использовать уведомления для обновления первого контроллера. Вот пример использования делегатов:

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.
}

Большое спасибо! Ты мой герой на сегодня :)

sirekpiotr 11.06.2019 17:58

Эй, у меня есть вопрос, потому что это не сработало. Как я могу обновить свой собственный вид? Что я должен ввести внутри функции caffeineDataSaved.

sirekpiotr 11.06.2019 21:19

Во-первых, убедитесь, что новые данные действительно сохранены в БД. Во-вторых, перезагрузите представление с новыми данными в методе делегата. вам нужно передать новые данные в TodaySummaryView. Для этого есть несколько способов: либо реализовать функцию, которая обновляет пользовательский интерфейс новыми данными, либо переопределить LayoutSubviews и сделать это там с переданным объектом данных.

Lirik 11.06.2019 21:50

В FirstVieeController в функции делегата я написал todaySummaryView.todayCoffeeAmount = countTodayCaffeineAmount и todaySummaryView.caffeineState = getCaffeineUserState, и ничего не произошло :(

sirekpiotr 11.06.2019 22:22

Я хочу еще раз сказать спасибо. Сегодня с хладнокровием реализовал протокол с функцией presetState() и все работает! Я отмечаю ваш ответ как решенный :)

sirekpiotr 12.06.2019 17:44

Другие вопросы по теме