以编程方式获取嵌入在 UIStackView 中的自定义 UIView

Posted

技术标签:

【中文标题】以编程方式获取嵌入在 UIStackView 中的自定义 UIView【英文标题】:Programmatically get the custom UIViews embedded inside UIStackView 【发布时间】:2019-05-03 05:41:21 【问题描述】:

在我的 ViewController 中,我有 12 个自定义 UIViews(命名为 CardView)。

我正在尝试以编程方式遍历ViewController 的子视图以找到自定义视图(CardView)并进行一些配置。以下是我计算 CardView 数量的代码。

    private func cardCount()->Int
            var count = 0
            for subview in self.view.subviews
                if subview is CardView
                    count = count + 1
                
            
            return count
    

但是,它返回“0”,原因是我的观点嵌入在 UIStackViews 中。我在一个垂直对齐的视图中有 3 个水平对齐的堆栈视图-

如何以编程方式获取我的 CardViews。任何帮助,将不胜感激。

【问题讨论】:

使用属性排列子视图而不是子视图 您可以将collectionView用于这种UI。这是更好的方法 亲爱的,我认为您可以一次又一次地循环访问卡片视图 第一个循环用于垂直堆栈视图,第二个用于水平堆栈视图,最后一个用于访问卡片 我认为,您应该通过使用集合视图项内的堆栈视图或表格视图单元格来更改此处的 ui 呈现逻辑。但是为了在这里回答您的查询,您可以创建容器stack view 的实例并迭代子stack views。这样,您将获得个人stack views,第二次迭代将针对个人stack views,以获得subviews 【参考方案1】:

你可以先做一些平面地图来扁平化你的视图结构,然后再计算它们:

private func cardCount()->Int

    var count = 0
    for subview in self.view.subviews.flatMap  $0.subviews .flatMap  $0.subviews 
        if subview is CardView
            count = count + 1
        
    
    return count


但我觉得你做错了事。卡的数量听起来像是您模型中的内容。您应该有一个名为cardCount 的变量,并且屏幕上的卡片应该根据该变量而改变,而不是相反。

【讨论】:

【参考方案2】:

您为每个水平堆栈视图创建 IBOutlets。然后循环遍历stackviews中的子视图。

@IBOutlet weak var StackView1: UIStackView!
@IBOutlet weak var StackView2: UIStackView!
@IBOutlet weak var StackView3: UIStackView!



  for customView in StackView1.arrangedSubviews
  
     // Do task
  

【讨论】:

【参考方案3】:

试试这个

private func cardCount() -> Int

    var count = 0
    for subview in self.view.subviews
    
        if let stackView: UIStackView = subview as? UIStackView
        
            let arrangedViews = stackView.arrangedSubviews
            for cardView in arrangedViews
            
                if cardView is CardView
                
                    count = count + 1
                
            

        
    
    return count

【讨论】:

【参考方案4】:

从您分享的图示来看,StackView 似乎是第一个孩子。每当您获得子视图时,只会返回第一个子视图。所以self.view.subviews 只会产生一个UIStackView。给每个堆栈视图一个标签。然后,在代码中:

private func cardCount()->Int
        var count = 0
        for subview in self.view.subviews
            if subview.tag == 10   // parent stack view
                 for subviewStack in subview   // Get subviews of parent stackview
                      if subviewStack.tag == 11   // First stack view child
                          for subViewSubStack in subviewStack.subviews  // Get card views in this stack view
                              // Apply your count logic 
                          
                      
                 

            
        
        return count
  

我只写了第一个条件。您可以添加其他人。 说了这么多,我不会说这是最优化的解决方案。这可以而且应该被重构。

【讨论】:

@Sweeper 的解决方案是我所写内容的重构版本。【参考方案5】:

像这样创建一个扩展方法。它将计算视图控制器中的所有 CardView 实例。

extension UIView 
    func cardCount() -> Int 
        switch self 
        case let self as CardView:
            return 1
        case let self as UIStackView:
            return self.arrangedSubviews.reduce(0,  $0 + $1.cardCount() )
        default:
            return self.subviews.reduce(0,  $0 + $1.cardCount() )
        
    

并在viewDidLoad中调用此方法

class ViewControllerd: UIViewController 
    override func viewDidLoad() 
        super.viewDidLoad()
        print(self.view.cardCount())
    

【讨论】:

以上是关于以编程方式获取嵌入在 UIStackView 中的自定义 UIView的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式未添加到 UIStackView 的元素?

以编程方式清空 UIStackView

以编程方式填充 UIStackView

如何以编程方式在 IOS 的 UIStackView 中重新排序项目?

以编程方式在 UIScrollView 中使用 UIStackView

以编程方式在 UIStackView 中添加视图