You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 21:27:33