web-dev-qa-db-fra.com

Comment référencer le contrôleur d'une classe uitableviewcell dans Swift

J'ai le suivant

  1. ViewController
  2. tableView
  3. CustomCell

J'ai utilisé un NIB (un fichier .xib) pour la cellule, qui utilise une classe CustomCell. Cette classe de cellule personnalisée gère IBAction pour une touche sur le bouton de la cellule. Je voudrais faire référence au ViewController et à certaines de ses variables. Comment suis-je censé le faire (accéder à ViewController)?

Merci!

33
Norly Canarias

Je ne créerais pas ce type de dépendance entre la cellule et le contrôleur de vue - cela rend l'architecture plus complexe et la cellule non réutilisable.

Je vous suggère d'utiliser le modèle de délégation, ce qui peut sembler un peu compliqué - bien que vous l'utilisiez déjà (UITableViewDelegate est un exemple typique):

  • créer un protocole MyCellProtocol avec une méthode didTapCell, en acceptant un UITableViewCell et/ou certaines données personnalisées que vous souhaitez transmettre au contrôleur de vue
  • créez une propriété de délégué public dans votre cellule personnalisée: weak var cellDelegate: MyCellProtocol?
  • dans le gestionnaire didTapXXX ou didSelectRowAtIndexPath de votre cellule, appelez self.cellDelegate?.didTapCell(), en passant les paramètres attendus
  • dans votre contrôleur de vue, implémentez le MyCellProtocol
  • dans cellForRowAtIndexPath de votre contrôleur de vue, lors de la création/retrait de la cellule, définissez sa propriété cellDelegate sur self

À ce stade, lorsqu'un tap est effectué dans votre cellule, la méthode didTapCell du contrôleur de vue est appelée, et à partir de là, vous pouvez faire tout ce que vous devez réaliser.

Le point clé est le suivant: plutôt que de faire en sorte que la cellule gère le tap/selection de cellule, informez le contrôleur de vue et laissez-le faire le travail.

47
Antonio
extension UIView {
    var parentViewController: UIViewController? {
        var parentResponder: UIResponder? = self
        while parentResponder != nil {
            parentResponder = parentResponder!.next
            if let viewController = parentResponder as? UIViewController {
                return viewController
            }
        }
        return nil
    }
}

À l'intérieur de ta cellule

if let myViewController = parentViewController as? MyViewController {
    print(myViewController.title)
}
19
Blank

Je ne pense pas que vous devriez faire cela et vous faites probablement quelque chose de mal, mais si vous en avez vraiment besoin, alors il suffit d'avoir une propriété dans votre classe CustomCell.

var viewController : UIViewController

puis lorsque vous créez la cellule dans cellForRowAtIndexPath définissez la propriété

cell.viewController = self

après cela, vous pouvez facilement accéder au contrôleur de vue depuis le code de la cellule:

self.viewController.doSomething()

Mais encore une fois, à mon avis, vous devriez reconcevoir votre code. La cellule ne doit pas se soucier du contrôleur. Il ne devrait se soucier que de s'afficher et de rien d'autre

13
Andrey Chernukha

ajouter une extension

 extension UITableViewCell {

        var viewControllerForTableView : UIViewController?{
            return ((self.superview as? UITableView)?.delegate as? UIViewController)
        }

    }

maintenant downCast comme ci-dessous

   if let viewController = self.viewControllerForTableView as? AnyController{

       print(viewController.variable)

   } 

.

2
Gopal krishan

Le meilleur moyen est de mettre en œuvre la délégation. Votre délégué informera le contrôleur de vue du clic sur le bouton. Et, à son tour, votre contrôleur de vue (qui conforme le protocole pour le délégué ci-dessus) gérera la tâche que vous souhaitez effectuer lors d'un événement de clic. (Des didacticiels sur les modèles de délégation sont disponibles en ligne. Vous pouvez les parcourir si vous voulez savoir comment effectuer la délégation).

2
Tejas

Lisez les autres commentaires sur le fait de vouloir vraiment utiliser une approche alternative avant d'essayer, mais l'utilisation de cette extension vous permettra d'accéder aux dataSource et delegate qui devraient tous deux être les UITableViewController

extension UITableViewCell {
    var tableView:UITableView? {
        get {
            for var view = self.superview ; view != nil ; view = view!.superview {
                if view! is UITableView {
                    return (view! as UITableView)
                }
            }
            return nil
        }
    }

    var tableViewDataSource:UITableViewDataSource? {
        get {
            return self.tableView?.dataSource
        }
    }

    var tableViewDelegate:UITableViewDelegate? {
        get {
            return self.tableView?.delegate
        }
    }
}
0
David Berry