J'essaie donc d'afficher une UIView dans une vue de pile lorsque je clique sur continuer sur un contrôleur et que je reviens au contrôleur précédent. Cependant, j'ai du mal à afficher la vue lorsque je pop. Il s'affichera si je présente le contrôleur, mais j'ai besoin qu'il s'affiche lorsque je pop. Comment dois-je procéder? Merci.

// ServiceDetailController

// MARK: - Properties

lazy var dateContainer: ShadowCardView = {
    let view = ShadowCardView()
    view.backgroundColor = .white
    view.addShadow()
    view.setHeight(height: 40)
        
    let stack = UIStackView(arrangedSubviews: [calendarIcon, dateLabel, timeOfDayLabel])
    stack.axis = .horizontal
    stack.distribution = .fillProportionally
    stack.spacing = 8
        
    view.addSubview(stack)
    stack.centerY(inView: view)
    stack.anchor(left: view.leftAnchor, right: view.rightAnchor, paddingLeft: 12, paddingRight: 70)
        
    view.addSubview(closeButton)
    closeButton.centerY(inView: view)
    closeButton.anchor(right: view.rightAnchor, paddingRight: 12)
        
    return view
}()

lazy var dateStack = UIStackView(arrangedSubviews: [dateLabelStack, dateContainer, dateContainerView])

// MARK: - Lifecycle

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

// MARK: - Selectors

@objc func handleDateCreationTapped() {
    let controller = DateCreationController()
    controller.jobService = self.jobService
    navigationController?.pushViewController(controller, animated: true)
}

// MARK: - Helper Functions

fileprivate func configureUI() {
        
     setupNavigationBar()
        
     view.backgroundColor = .groupTableViewBackground
        
     setupServiceInfoView()
        
     setupFormView()
        
}

fileprivate func setupFormView() {
        
    showDataContainer(shouldShow: false)
    setupTapGestureRecognizers()
        
}

fileprivate func setupTapGestureRecognizers() {
        
     let dateTap = UITapGestureRecognizer(target: self, action: #selector(handleDateCreationTapped))
     dateTap.numberOfTapsRequired = 1
     dateTextField.addGestureRecognizer(dateTap)
        
}

func showDateContainer(shouldShow: Bool) {
            
       if shouldShow {
          dateContainer.isHidden = false
          dateStack.spacing = 5
       } else {
          dateContainer.isHidden = true
          dateStack.spacing = -18
       }
            
 }

// DateCréationController

// MARK: - Properties

private let continueButton: UIButton = {
     let button = UIButton(type: .system)
     button.setTitle("Continue", for: .normal)
     button.setTitleColor(.white, for: .normal)
     button.titleLabel?.font = UIFont(name: "AvenirNext-Medium", size: 14)
     button.backgroundColor = .darkGray
     button.setHeight(height: 50)
     button.layer.cornerRadius = 8
     button.addTarget(self, action: #selector(handleContinue), for: .touchUpInside)
     return button
}()

// MARK: - Selectors

@objc func handleContinue() {
        
    let controller = ServiceDetailController()
    controller.showDateContainer(shouldShow: true)
        
    navigationController?.popViewController(animated: true)

}
0
Zachary Smouse 17 nov. 2020 à 08:34

1 réponse

Meilleure réponse

Le problème principal est cette fonction dans votre DateCreationController :

@objc func handleContinue() {
        
    // here, you are creating a NEW instance of ServiceDetailController
    let controller = ServiceDetailController()
    controller.showDateContainer(shouldShow: true)
        
    // here, you are popping back to where you came from... the EXISTING instance of ServiceDetailController
    navigationController?.popViewController(animated: true)

}

Vous devez utiliser un modèle délégué/protocole ou une fermeture.

Voici un exemple utilisant une fermeture...

Ajoutez cette variable à votre classe DateCreationController :

var continueCallback: ((Bool)->())?

Dans votre classe ServiceDetailController, lorsque vous instanciez et poussez votre DateCreationController, vous configurerez également cette fermeture :

@objc func handleDateCreationTapped() {
    let controller = DateCreationController()
    controller.jobService = self.jobService
    
    // add the closure
    controller.continueCallback = { [weak self] shouldShow in
        guard let self = self else { return }
        self.showDateContainer(shouldShow: shouldShow)
        self.navigationController?.popViewController(animated: true)
    }

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

Ensuite, dans votre action de bouton dans DateCreationController, vous "rappelez" en utilisant cette fermeture :

@objc func handleContinue() {
    
    continueCallback?(true)
    
}

Voici un exemple exécutable. Il crée une simple vue jaune comme la vue dateContainer, mais elle est masquée au chargement. Taper n'importe où poussera sur DateCreationController, qui a un seul bouton "Continuer". Appuyez sur ce bouton pour exécuter la fermeture, où la vue dateContainer sera définie sur visible et nous reviendrons pop :

class ServiceDetailController: UIViewController {
    
    var jobService: String = "abc"

    // plain yellow view
    let dateContainer: UIView = {
        let view = UIView()
        view.backgroundColor = .yellow
        return view
    }()
    
    // MARK: - Lifecycle
    
    override func viewDidLoad() {
        super.viewDidLoad()

        let infoLabel = UILabel()
        infoLabel.text = "Tap anywhere"
        view.addSubview(infoLabel)
        view.addSubview(dateContainer)
        
        infoLabel.translatesAutoresizingMaskIntoConstraints = false
        dateContainer.translatesAutoresizingMaskIntoConstraints = false
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            infoLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
            infoLabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            
            dateContainer.topAnchor.constraint(equalTo: infoLabel.bottomAnchor, constant: 20.0),
            dateContainer.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            dateContainer.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            dateContainer.heightAnchor.constraint(equalToConstant: 100.0),
        ])

        setupTapGestureRecognizers()
        
        // hide dateContainer on load
        showDateContainer(shouldShow: false)
    }
    
    // MARK: - Selectors
    
    @objc func handleDateCreationTapped() {
        let controller = DateCreationController()
        controller.jobService = self.jobService
        
        // add the closure
        controller.continueCallback = { [weak self] shouldShow in
            guard let self = self else { return }
            self.showDateContainer(shouldShow: shouldShow)
            self.navigationController?.popViewController(animated: true)
        }

        navigationController?.pushViewController(controller, animated: true)
    }
    
    // MARK: - Helper Functions
    
    fileprivate func setupTapGestureRecognizers() {
        
        let dateTap = UITapGestureRecognizer(target: self, action: #selector(handleDateCreationTapped))
        dateTap.numberOfTapsRequired = 1
        view.addGestureRecognizer(dateTap)
        
    }
    
    func showDateContainer(shouldShow: Bool) {
        
        if shouldShow {
            dateContainer.isHidden = false
        } else {
            dateContainer.isHidden = true
        }
        
    }
}
class DateCreationController: UIViewController {
    var jobService: String = "abc"
    
    var continueCallback: ((Bool)->())?
    
    lazy var continueButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("Continue", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.titleLabel?.font = UIFont(name: "AvenirNext-Medium", size: 14)
        button.backgroundColor = .darkGray
        button.layer.cornerRadius = 8
        button.addTarget(self, action: #selector(handleContinue), for: .touchUpInside)
        return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .green
        view.addSubview(continueButton)
        continueButton.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            continueButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            continueButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            continueButton.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.75),
            continueButton.heightAnchor.constraint(equalToConstant: 50.0),
        ])
    }
    
    // MARK: - Selectors
    
    @objc func handleContinue() {
        
        continueCallback?(true)
        
    }
}
0
DonMag 18 nov. 2020 à 21:55