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

iOS Swift中为Tab添加底部边框不显示的问题求助

问题原因

你在viewDidLoad中调用addBorder时,segmentedControl的frame还没通过AutoLayout计算出正确值——此时它的frame是初始空值或默认尺寸,导致底部边框被放在错误位置(比如超出屏幕可见区域),所以看不到红色边框。

解决方案

下面提供两种可靠的修复方式:

方式一:在布局完成后添加边框

将添加边框的逻辑移到viewDidLayoutSubviews中,这个方法会在AutoLayout完成布局、view的frame确定后调用。同时要避免重复添加边框:

修改ViewController代码

import UIKit

class ViewController: UIViewController {
    // 将segmentedControl改为类属性,方便在viewDidLayoutSubviews中访问
    private let segmentedControl = UIStackView()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.view.backgroundColor = .systemBackground
        
        self.navigationItem.titleView = UIImageView(
          image: UIImage(named: "Twitter")!.resize(25, 25)
        )
        
        let leftBarImage = UIImageView(
          image: UIImage(named: "Profile")!.resize(35, 35)
        )
        leftBarImage.layer.borderWidth = 1
        leftBarImage.layer.borderColor = UIColor.systemGray4.cgColor
        leftBarImage.layer.cornerRadius = leftBarImage.frame.width / 2
        leftBarImage.clipsToBounds = true
        
        self.navigationItem.leftBarButtonItem = UIBarButtonItem(
          customView: leftBarImage
        )
        
        segmentedControl.translatesAutoresizingMaskIntoConstraints = false
        segmentedControl.axis = .horizontal
        segmentedControl.alignment = .center
        segmentedControl.distribution = .fillEqually
        segmentedControl.backgroundColor = .green
          
        for menuLabelText in ["For you", "Following"] {
          let menuLabel = UILabel()
          menuLabel.text = menuLabelText
          menuLabel.textAlignment = .center
          menuLabel.font = UIFont.boldSystemFont(ofSize: 16)
          
          segmentedControl.addArrangedSubview(menuLabel)
        }
        
        self.view.addSubview(segmentedControl)
        
        NSLayoutConstraint.activate([
          segmentedControl.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
          segmentedControl.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor)
        ])
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        // 先移除已存在的底部边框,避免重复添加
        segmentedControl.layer.sublayers?.forEach { layer in
            if layer.name == "BottomBorder" {
                layer.removeFromSuperlayer()
            }
        }
        // 添加底部边框
        segmentedControl.addBorder(for: .Bottom, color: UIColor.red.cgColor, thickness: 20)
    }
}

修改UIView扩展(给边框加标识)

import UIKit

extension UIView {
    enum BorderSide {
        case Left, Right, Top, Bottom
    }

    func addBorder(for side: BorderSide, color: CGColor, thickness: CGFloat) {
        let border = CALayer()
        border.backgroundColor = color
        border.name = "BottomBorder" // 添加标识,方便后续移除
        
        switch side {
          case .Left:
            border.frame = CGRect(
              x: frame.minX,
              y: frame.minY,
              width: thickness,
              height: frame.height
            )
          case .Right:
            border.frame = CGRect(
              x: frame.maxX,
              y: frame.minY,
              width: thickness,
              height: frame.height
            )
          case .Top:
            border.frame = CGRect(
              x: frame.minX,
              y: frame.minY,
              width: frame.width,
              height: thickness
            )
          case .Bottom:
            border.frame = CGRect(
              x: frame.minX,
              y: frame.maxY,
              width: frame.width,
              height: thickness
            )
        }

        layer.addSublayer(border)
    }
}

方式二:用AutoLayout创建边框(更推荐)

放弃依赖frame的CALayer方式,改用UIView+AutoLayout实现边框,这样边框会自动跟随view的布局变化,无需担心frame问题:

重写UIView扩展

import UIKit

extension UIView {
    enum BorderSide {
        case left, right, top, bottom
    }

    func addBorder(for side: BorderSide, color: UIColor, thickness: CGFloat) {
        let borderView = UIView()
        borderView.backgroundColor = color
        borderView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(borderView)

        let constraints: [NSLayoutConstraint]
        switch side {
        case .left:
            constraints = [
                borderView.leadingAnchor.constraint(equalTo: leadingAnchor),
                borderView.topAnchor.constraint(equalTo: topAnchor),
                borderView.bottomAnchor.constraint(equalTo: bottomAnchor),
                borderView.widthAnchor.constraint(equalToConstant: thickness)
            ]
        case .right:
            constraints = [
                borderView.trailingAnchor.constraint(equalTo: trailingAnchor),
                borderView.topAnchor.constraint(equalTo: topAnchor),
                borderView.bottomAnchor.constraint(equalTo: bottomAnchor),
                borderView.widthAnchor.constraint(equalToConstant: thickness)
            ]
        case .top:
            constraints = [
                borderView.leadingAnchor.constraint(equalTo: leadingAnchor),
                borderView.trailingAnchor.constraint(equalTo: trailingAnchor),
                borderView.topAnchor.constraint(equalTo: topAnchor),
                borderView.heightAnchor.constraint(equalToConstant: thickness)
            ]
        case .bottom:
            constraints = [
                borderView.leadingAnchor.constraint(equalTo: leadingAnchor),
                borderView.trailingAnchor.constraint(equalTo: trailingAnchor),
                borderView.bottomAnchor.constraint(equalTo: bottomAnchor),
                borderView.heightAnchor.constraint(equalToConstant: thickness)
            ]
        }
        NSLayoutConstraint.activate(constraints)
    }
}

修改ViewController中的调用

在viewDidLoad中直接调用即可,无需移到viewDidLayoutSubviews:

segmentedControl.addBorder(for: .bottom, color: .red, thickness: 20)
补充说明

AutoLayout的布局计算流程是:viewDidLoad → viewWillAppear → 布局计算 → viewDidLayoutSubviews。所以在viewDidLoad阶段,所有用AutoLayout约束的view的frame都还未确定,此时基于frame的操作都会出错。

内容的提问来源于stack exchange,提问作者Axel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 21:35:16