Swift中点击按钮隐藏/显示Xib视图及返回后视图不显示问题排查
问题原因与解决方案
原因分析
核心问题出在全局单例的adView实例:
- 第一次调用
addAdvertisementView时,会给adView绑定与当前adContainerView的布局约束并激活。 - 当你离开
MessageList控制器(控制器被销毁),原adContainerView被释放,但全局adView仍存在,且身上绑定的旧约束并未被清除。 - 重新进入
MessageList时,再次调用addAdvertisementView会把adView添加到新的adContainerView,同时添加新约束。此时adView身上存在两组冲突的约束,系统会自动丢弃部分约束,导致adView无法正确布局显示;或者旧约束失效后新约束未正确生效,最终导致adView不可见。
另外,如果控制器未被销毁(如push出去再返回),viewDidLoad仅执行一次,但若adView因其他原因被移出父视图,也会出现显示问题。
解决方案
方案一:移除全局单例,每次创建新的adView实例
这种方式最稳妥,每个MessageList控制器实例拥有独立的adView,避免约束冲突和复用问题。
修改global.swift(或直接把方法移到控制器内):
func addAdvertisementView(containerView: UIView) -> AdvertisementView { let adView = AdvertisementView() containerView.isHidden = false containerView.clipsToBounds = true containerView.addSubview(adView) adView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ adView.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 5), adView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -5), adView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 5), adView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -5) ]) return adView }
修改MessageList控制器代码:
class MessageList: UIViewController, SampleButtonViewDelegate { @IBOutlet weak var adContainerView: UIView! private var adView: AdvertisementView? override func viewDidLoad() { super.viewDidLoad() setupAdView() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) adContainerView.isHidden = false // 如果需要每次进入都刷新广告,可在这里重新创建adView // setupAdView() } private func setupAdView() { adView = addAdvertisementView(containerView: adContainerView) adView?.delegate = self } func sampleButtonTapped() { adContainerView.isHidden = true } }
方案二:保留全局单例,添加前清除旧约束
如果必须使用全局adView,需在每次添加到新容器前,清除旧的父视图和约束:
修改global.swift:
let adView = AdvertisementView() func addAdvertisementView(containerView: UIView) { containerView.isHidden = false containerView.clipsToBounds = true // 清除adView之前的父视图和约束 adView.removeFromSuperview() adView.constraints.forEach { $0.isActive = false } adView.removeConstraints(adView.constraints) containerView.addSubview(adView) adView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ adView.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 5), adView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -5), adView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 5), adView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -5) ]) }
修改MessageList控制器代码:
class MessageList: UIViewController, SampleButtonViewDelegate { @IBOutlet weak var adContainerView: UIView! override func viewDidLoad() { super.viewDidLoad() setupAdView() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) adContainerView.isHidden = false setupAdView() } private func setupAdView() { addAdvertisementView(containerView: adContainerView) adView.delegate = self } func sampleButtonTapped() { adContainerView.isHidden = true } }
内容的提问来源于stack exchange,提问作者Json Swift
相关产品推荐
相关产品推荐

