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

iOS Swift UIKit开发:如何在自定义UIView中复制带数字1234的蓝色盒子

核心问题

你现在代码的问题出在三个地方:

  • 你用来展示蓝色框的stackPipe、展示数字的lblTitleCompo都是全局唯一的实例属性,同一个UIView实例不能被重复添加到父视图上,你在循环里反复执行addSubview操作,只会把这个唯一的视图来回移动父视图,不会生成新的蓝色框,自然看不到多个复制的效果。
  • products是UIScrollView,你没有给它的内部子视图设置底部约束来撑开contentSize,就算你加了多个视图也会布局混乱、无法滚动。
  • 你的视图添加逻辑重复:init里执行了一次循环加视图,又调用listSubviewsOfView再跑了一次循环,后面setupView里又单独加了一次stackPipe,逻辑完全冲突。

修复步骤

第一步:删除全局的stackPipe、lblTitleCompo实例属性,改成在循环里每次创建新实例

第二步:给循环里创建的每个蓝色框设置竖向约束,按顺序排列,最后一个蓝色框的底部约束到products的底部,撑开滚动视图的内容尺寸

第三步:清理重复的视图添加逻辑,只在setupView里执行一次生成多个蓝色框的逻辑

核心修改代码片段

// 首先删除原来的全局 stackPipe、lblTitleCompo 定义,以及init、listSubviewsOfView里的循环加视图逻辑
// 在setupView里添加以下逻辑:
// 用来记录上一个蓝色框的底部,方便做竖向约束
var lastViewBottom: CGFloat = 25
let cardHeight: CGFloat = 100
let cardSpacing: CGFloat = 15

for index in 1...5 {
    // 每次循环创建新的蓝色框stackPipe
    let stackPipe = UIStackView().usingAutoLayout()
    stackPipe.axis = .vertical
    stackPipe.alignment = .fill
    stackPipe.isLayoutMarginsRelativeArrangement = true
    stackPipe.layoutMargins = UIEdgeInsets(top: 30, left: 15, bottom: 30, right: 15)
    stackPipe.roundedCornersAndShadow()
    stackPipe.backgroundColor = .newBlue
    
    // 每次循环创建新的数字label
    let lblTitleCompo = UILabel().usingAutoLayout()
    lblTitleCompo.textAlignment = .center
    lblTitleCompo.numberOfLines = 3
    lblTitleCompo.adjustsFontSizeToFitWidth = true
    // 这里可以改成动态显示不同的数字,比如"\(index)234"
    lblTitleCompo.attributedText = "\(index)234".localized().book20(.slateGray)
    
    stackPipe.addArrangedSubview(lblTitleCompo)
    products.addSubview(stackPipe)
    
    // 给当前蓝色框加约束
    constrain(stackPipe, lblTitleCompo) { stackPipe, lblTitleCompo in
        stackPipe.leading == products.leading + 10
        stackPipe.trailing == products.trailing - 10
        stackPipe.top == products.top + lastViewBottom
        stackPipe.height == cardHeight
        
        lblTitleCompo.top == stackPipe.top - 10
        lblTitleCompo.leading == stackPipe.leading + 10
        lblTitleCompo.trailing == stackPipe.trailing - 10
    }
    
    // 更新lastViewBottom,下一个蓝色框排在当前的下面
    lastViewBottom += cardHeight + cardSpacing
    // 把生成的控件存到全局数组里方便后续使用
    buttons.append(lblTitleCompo)
}

// 最后加约束撑开products的contentSize,要在循环结束后执行
constrain(products) { products in
    products.bottomAnchor.constraint(equalTo: products.subviews.last!.bottomAnchor, constant: 25).isActive = true
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 03:54:03