在导航控制器上弹回时显示 UIView

Show UIView When Popping Back on a Navigation Controller

因此,当我在控制器上单击“继续”并弹回到上一个控制器时,我试图在堆栈视图中显示一个 UIView。但是,我在弹出时无法显示视图。它会显示我是否出示控制器,但我需要它在我弹出时显示。我该怎么办?谢谢。

// 服务细节控制器

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

// 日期创建控制器

// 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)

}

主要问题是您 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)

}

您需要使用 delegate/protocol 模式或闭包。

这是一个使用闭包的例子...

将此变量添加到您的 DateCreationController class:

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

在您的 ServiceDetailController class 中,当您实例化并推送 DateCreationController 时,您还将设置该闭包:

@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)
}

然后,在 DateCreationController 中的按钮操作中,您使用该闭包“回调”:

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

这是一个可运行的例子。它创建一个简单的黄色视图作为 dateContainer 视图,但它在加载时隐藏。点击任意位置将推送到 DateCreationController,其中有一个“继续”按钮。点击该按钮将执行关闭,其中 dateContainer 视图将设置为可见,我们将 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)
        
    }
}