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

Swift:如何基于对象数组复用已有UIView动态添加至UIStackView?

解决方法:基于模板视图生成多份实例并填充数据

问题原因

你当前的代码存在两个核心问题:

  • 同一个companyShow视图实例不能被多次添加到栈视图中,UIKit规则是一个视图只能属于一个父视图,重复添加只会保留最后一次的操作结果。
  • 你修改的是同一个companyName标签的文本,循环结束后自然只会显示最后一个公司的名称。

解决方案1:视图拷贝+Tag查找标签

将Storyboard中的companyShow作为模板,通过拷贝生成新视图,再通过Tag定位标签填充数据:

  1. 先给UIView添加拷贝扩展:
extension UIView {
    func copyView() -> UIView? {
        guard let archivedData = try? NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false),
              let copiedView = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(archivedData) as? UIView else {
            return nil
        }
        copiedView.frame = self.frame
        return copiedView
    }
}
  1. 修改控制器viewDidLoad代码:
override func viewDidLoad() {
    super.viewDidLoad()
    
    let companies = [
        Company(owner: "jan"),
        Company(owner: "henk"),
    ]
    
    // 移除模板视图,避免显示原控件
    companyShow.removeFromSuperview()
    
    for company in companies {
        // 拷贝模板视图
        guard let companyViewCopy = companyShow.copyView() else { continue }
        // 通过Tag获取副本内的标签(需提前在Storyboard给companyName设置Tag,比如100)
        if let nameLabel = companyViewCopy.viewWithTag(100) as? UILabel {
            nameLabel.text = company.owner
        }
        // 添加到栈视图
        allCompaniesShow.addArrangedSubview(companyViewCopy)
    }
}

注意:需要在Storyboard中选中companyName标签,在Attributes Inspector里设置Tag值为100(或其他自定义数值)。


解决方案2:自定义UIView子类(推荐)

这种方式更规范,避免Tag冲突问题,也更易维护:

  1. 创建自定义视图类CompanyView.swift:
import UIKit

class CompanyView: UIView {
    @IBOutlet weak var companyName: UILabel!
    
    // 加载自定义视图的类方法
    static func instantiate() -> CompanyView {
        let nib = UINib(nibName: "CompanyView", bundle: nil)
        return nib.instantiate(withOwner: nil, options: nil).first as! CompanyView
    }
}
  1. 在Storyboard中配置模板视图:
  • 选中companyShow视图,在Identity Inspector中将Class改为CompanyView。
  • 确保companyName标签已经和CompanyView中的IBOutlet关联。
  1. 修改控制器viewDidLoad代码:
override func viewDidLoad() {
    super.viewDidLoad()
    
    let companies = [
        Company(owner: "jan"),
        Company(owner: "henk"),
    ]
    
    // 隐藏原模板视图
    companyShow.isHidden = true
    
    for company in companies {
        let companyView = CompanyView.instantiate()
        companyView.companyName.text = company.owner
        allCompaniesShow.addArrangedSubview(companyView)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 05:01:11