2
votes

Obtenez les UIViews personnalisées intégrées dans UIStackView par programme

Dans mon ViewController , j'ai 12 UIViews personnalisés (nommés CardView).

 entrez la description de l'image ici

J'essaie de parcourir les sous-vues du ViewController par programmation pour trouver la vue personnalisée (CardView) et effectuer une configuration. Voici mon code pour compter le nombre de CardViews.

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

Cependant, il me renvoie «0» et la raison étant que mes vues sont intégrées dans UIStackViews code>. J'ai 3 vues de pile alignées horizontalement dans une vue alignée verticalement comme-

Comment puis-je obtenir mes CardViews par programmation. Toute aide serait appréciée.


7 commentaires

utiliser la propriété arrangéeSubviews au lieu de sous-vues


Vous pouvez utiliser collectionView pour ce type d'interface utilisateur. C'est la meilleure approche


Cher, je pense que vous pouvez faire une boucle encore et encore pour accéder aux vues de carte


première boucle pour la vue verticale de la pile, deuxième pour la vue horizontale de la pile et dernière pour accéder à la carte


Je pense que vous devriez changer la logique de rendu de l'interface utilisateur ici en utilisant soit la vue de la pile à l'intérieur de l'élément de vue de la collection, soit la cellule de la vue du tableau. Mais pour répondre à votre requête ici, vous pouvez créer une instance de la vue de la pile du conteneur et effectuer une itération pour les sous vues de la pile . De cette façon, vous obtiendrez des vues de pile individuelles et une deuxième itération serait pour les vues de pile individuelles pour en obtenir les sous-vues .


Pouvez-vous expliquer pourquoi vous comptez le nombre de cartes? Je sens une question XY.


Merci pour toutes les suggestions. Je sais qu'il existe quelques meilleures alternatives dans cette situation, mais je le fais à des fins d'apprentissage. Je pense que j'ai besoin de boucler jusqu'à ce qu'il n'y ait plus de stackviews.


5 Réponses :


1
votes

Vous créez des IBOutlets dans chacune des vues de pile horizontale. Ensuite, parcourez les sous-vues dans les vues de pile.

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



  for customView in StackView1.arrangedSubviews
  {
     // Do task
  }


0 commentaires

0
votes

Essayez ceci

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
}


0 commentaires

0
votes

D'après le diagramme illustré que vous avez partagé, il semble que StackView soit le premier enfant. Chaque fois que vous obtenez les sous-vues, seules les premières vues enfants sont renvoyées. Ainsi, self.view.subviews ne donnerait qu'un seul UIStackView . Donnez une balise à chaque vue de pile. Ensuite, dans le code:

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
}  

Je n'ai écrit que la première condition. Vous pourriez en ajouter d'autres.
Cela dit, je ne dirai pas que c'est la solution la plus optimale. Cela peut et doit être remanié.


1 commentaires

La solution de @ Sweeper est la version refactorisée de ce que j'ai écrit.



2
votes

Vous pouvez faire quelques plans plats pour aplatir d'abord votre structure de vue, puis les compter:

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

}

Mais j'ai l'impression que vous faites les choses dans le mauvais sens. Le nombre de cartes ressemble à quelque chose dans votre modèle. Vous devriez avoir une variable appelée cardCount et les cartes à l'écran sont censées changer en fonction de cette variable, et non l'inverse.


0 commentaires

0
votes

Créez une méthode d'extension comme celle-ci. Il comptera toutes les instances CardView dans le contrôleur de vue.

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

et appellera cette méthode dans viewDidLoad

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() })
        }
    }
}

p >


0 commentaires