2

Nous voulons afficher un autre contrôleur en remplaçant le contrôleur principal lorsque vous cliquez sur l'élément (i.e ImageView) à l'intérieur d'un cell collection. Mais nous ne sommes pas en mesure d'obtenir la vue de la collection principale et ne pouvons pas naviguer dans le contrôleur ciblé. Nous utilisons l'approche suivante -Comment naviguer dans un autre contrôleur de vue en cliquant sur l'élément dans la cellule de collectionView Utiliser Swift 3

enter image description here

HomeViewComtroller.swift

import LBTAComponents 

class HomeViewController: DatasourceController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     navigationItem.title = "Home" 
     collectionView?.contentInset = UIEdgeInsetsMake(50, 0, 0, 0) 
     collectionView?.scrollIndicatorInsets = UIEdgeInsetsMake(50, 0, 0, 0) 
     collectionView?.backgroundColor = UIColor(r: 232, g: 236, b: 241, a: 1) 
     let homeViewDatasource = HomeViewDatasource() 
     self.datasource = homeViewDatasource 
    } 


    override func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 

     if indexPath.section == 0 { 
      return CGSize(width: view.frame.width, height: 120) 
     } else if indexPath.section == 6 { 
      return CGSize(width: view.frame.width, height: 120) 
     } else { 
      return CGSize(width: view.frame.width, height: 200) 
      } 


    } 
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { 
      return CGSize(width: view.frame.width, height: 33) 
    } 
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { 
     return CGSize(width: view.frame.width, height: 10) 
    } 


// lazy var homeMainCatgCell: HomeMainCatgCell = { 
//  let homemain = HomeMainCatgCell() 
//  homemain.homeViewcontroller = self 
//  return homemain 
// }() 


    func handleCtgClick (ctgname: String ,ctgId: String) { 

     let dummySettingViewController = UIViewController() 
     dummySettingViewController.view.backgroundColor = UIColor.white 
     dummySettingViewController.navigationItem.title = ctgname 
     navigationController?.navigationBar.tintColor = UIColor.white 
     navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white] 
     navigationController?.pushViewController(dummySettingViewController, animated: true) 

    } 

} 

HomeViewDatasource

import LBTAComponents 

class HomeViewDatasource: Datasource { 

    override func headerClasses() -> [DatasourceCell.Type]? { 
     return [HomeMainCatgCellHeader.self,HomeSaleCatgCellHeader.self,HomeNewArrivalCellHeader.self,HomeBestSallingCellHeader.self,HomeBigDiscountCellHeader.self,HomeSpecialOfferCellHeader.self,HomeBrandCellHeader.self] 
    } 
    override func footerClasses() -> [DatasourceCell.Type]? { 
     return[HomeCellsFooter.self] 
    } 
    override func cellClasses() -> [DatasourceCell.Type] { 
     return [HomeMainCatgCell.self,HomeSaleCtagCell.self,HomeNewArrivalsCell.self,HomeBestSallingCatgCell.self,HomeBigDiscountCatgCell.self,HomeSpecialOfferCatgCell.self,HomeBrandVIewCell.self] 
    } 
    override func numberOfItems(_ section: Int) -> Int { 
     return 1 
    } 
    override func numberOfSections() -> Int { 
     return 7 
    } 
} 

HomeMainCatgCell.swift

import LBTAComponents 

class HomeMainCatgCell: DatasourceCell { 
    var homeViewcontroller: HomeViewController? 
    let personalcareCatgImageView: UIImageView = { 
     let iv = UIImageView() 
     iv.image = #imageLiteral(resourceName: "personalcareimage") 
     iv.tag = 0 
     iv.contentMode = .scaleToFill 
     return iv 
    }() 

    let healthcareCatgImageView: UIImageView = { 
     let iv = UIImageView() 
     iv.image = #imageLiteral(resourceName: "healthcareimage") 
     iv.contentMode = .scaleToFill 
     iv.tag = 1 
     return iv 
    }() 

    let homecareCatgImageView: UIImageView = { 
     let iv = UIImageView() 
     iv.image = #imageLiteral(resourceName: "homecareimage") 
     iv.contentMode = .scaleToFill 
     iv.tag = 2 
     return iv 
    }() 

    let kitchencareCatgImageView: UIImageView = { 
     let iv = UIImageView() 
     iv.image = #imageLiteral(resourceName: "kitchencareiamge") 
     iv.contentMode = .scaleToFill 
     iv.tag = 3 
     return iv 
    }() 


    override func setupViews() { 
     super.setupViews() 
     let personalcareCatgImageContainerView = UIView() 
     personalcareCatgImageContainerView.backgroundColor = .white 

     let homecareCatgImageContainerView = UIView() 
     homecareCatgImageContainerView.backgroundColor = .white 


     let healthcareCatgImageContainerView = UIView() 
     healthcareCatgImageContainerView.backgroundColor = .white 


     let kitchencareCatgImageContainerView = UIView() 
     kitchencareCatgImageContainerView.backgroundColor = .white 


     let imageStackView = UIStackView(arrangedSubviews: [personalcareCatgImageContainerView,homecareCatgImageContainerView,healthcareCatgImageContainerView,kitchencareCatgImageContainerView]) 
     imageStackView.axis = .horizontal 
     imageStackView.distribution = .fillEqually 
     addSubview(imageStackView) 
     imageStackView.anchor(topAnchor, left: leftAnchor, bottom: self.bottomAnchor, right: self.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: frame.width, heightConstant: frame.height) 

     imageStackView.addSubview(personalcareCatgImageView) 
     imageStackView.addSubview(healthcareCatgImageView) 
     imageStackView.addSubview(homecareCatgImageView) 
     imageStackView.addSubview(kitchencareCatgImageView) 

     personalcareCatgImageView.anchor(personalcareCatgImageContainerView.topAnchor, left: personalcareCatgImageContainerView.leftAnchor, bottom: personalcareCatgImageContainerView.bottomAnchor, right: personalcareCatgImageContainerView.rightAnchor, topConstant: 5, leftConstant: 5, bottomConstant: 5, rightConstant: 5, widthConstant: personalcareCatgImageContainerView.frame.width , heightConstant: personalcareCatgImageContainerView.frame.width) 

      healthcareCatgImageView.anchor(healthcareCatgImageContainerView.topAnchor, left: healthcareCatgImageContainerView.leftAnchor, bottom: healthcareCatgImageContainerView.bottomAnchor, right: healthcareCatgImageContainerView.rightAnchor, topConstant: 5, leftConstant: 5, bottomConstant: 5, rightConstant: 5, widthConstant: healthcareCatgImageContainerView.frame.width , heightConstant: healthcareCatgImageContainerView.frame.width) 

      homecareCatgImageView.anchor(homecareCatgImageContainerView.topAnchor, left: homecareCatgImageContainerView.leftAnchor, bottom: homecareCatgImageContainerView.bottomAnchor, right: homecareCatgImageContainerView.rightAnchor, topConstant: 5, leftConstant: 5, bottomConstant: 5, rightConstant: 5, widthConstant: homecareCatgImageContainerView.frame.width , heightConstant: homecareCatgImageContainerView.frame.width) 

      kitchencareCatgImageView.anchor(kitchencareCatgImageContainerView.topAnchor, left: kitchencareCatgImageContainerView.leftAnchor, bottom: kitchencareCatgImageContainerView.bottomAnchor, right: kitchencareCatgImageContainerView.rightAnchor, topConstant: 5, leftConstant: 5, bottomConstant: 5, rightConstant: 5, widthConstant: kitchencareCatgImageContainerView.frame.width , heightConstant: kitchencareCatgImageContainerView.frame.width) 

     personalcareCatgImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleClickCtg))) 
     personalcareCatgImageView.isUserInteractionEnabled = true 
     healthcareCatgImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleClickCtg))) 
     healthcareCatgImageView.isUserInteractionEnabled = true 
     homecareCatgImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleClickCtg))) 
     homecareCatgImageView.isUserInteractionEnabled = true 
     kitchencareCatgImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleClickCtg))) 
     kitchencareCatgImageView.isUserInteractionEnabled = true 
    } 

    func handleClickCtg(gestureRecognizer: UITapGestureRecognizer) { 
     var CtgName: String? = nil 
     var CtgId: String? = nil 
     guard let tag = gestureRecognizer.view?.tag else {return} 
     print(tag) 
     switch tag { 
     case 0: 
      CtgName = "Personal Care" 
      CtgId = "121" 
     case 1: 
      CtgName = "Health Care" 
      CtgId = "122" 
     case 2: 
      CtgName = "Home Care" 
      CtgId = "123" 
     case 3: 
      CtgName = "Kitchen Care" 
      CtgId = "124" 
     default: 
      return 
     } 
     self.homeViewController?.handleCtgClick(ctgname: CtgName! ,ctgId: CtgId!) 
    } 
} 

Problème principal

d'abord je ne suis pas se lier clic de cellule entière, je veux seulement cliquer sur bing ImageView dans la cellule. Donc, pour que je lie GestureRecognizer sur la vue d'image comme -

kitchencareCatgImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleClickCtg))) 

événement Click fonctionne très bien en termes de celui-ci est imprimé l'étiquette (ajoutée sur la vue de l'image) via print(tag) à l'intérieur de la fonction clic. Mais quand appelez la fonction self.homeViewcontroller.handleCtgClick(ctgname: CtgName! ,ctgId: CtgId!) (la fonction existe dans la classe HomeViewcontroller). ça ne change pas le contrôleur de vue.

Je débogue également la fonction handleCtgClick et j'ai trouvé que l'objet de HomeViewcontroller est nil.

Merci à l'avance

+0

Pouvez-vous être plus précis quant à quel est le problème réel? Quelles erreurs obtenez-vous? ou quoi de mal? (Les gens ne devraient pas avoir à passer par votre code pour trouver ce qui est faux, vous devriez le signaler.) – Pochi

+0

Pouvez-vous montrer la méthode 'cellForItemAt'. –

+0

assurez-vous que ViewController est incorporé dans UINavigationController. Sinon, il ne poussera pas le ViewController. – MacKa

Répondre

1

Si vous déclarez une instance globale de votre contrôleur dans votre classe de cellule, cela créera un cycle de référence et créera une fuite dans votre application. Votre cellule aura une forte référence à votre contrôleur et votre contrôleur aura une référence forte à votre vue de table qui à son tour garde une forte référence à la cellule, et en second lieu vous pourriez ne pas être en mesure de dire le chemin d'index de la cellule cliquée si vous permettre l'édition. Vous pouvez essayer la méthode suivante pour surmonter les deux problèmes. Tout d'abord, créez une énumération dans votre classe de cellule avec des observations nommées en fonction de vos vues d'image afin que votre contrôleur sache quelle vue d'image est cliquée et que vous puissiez y associer vos étiquettes. Quelque chose comme:

enum CategoryViews:Int{ 
    case personal = 0,healthcare = 1,homecare = 2,kitchencare = 3 
} 

Ensuite, créez un protocole dans votre classe cellulaire comme:

protocol HomeMainCatgCellDelegate:class{ 
    func clicked(view:CategoryViews,forCell cell:HomeMainCatgCell) 
} 

Ensuite, créez une variable faible dans votre classe cellulaire et appeler la méthode de protocole dans votre méthode de gestionnaire d'action

class HomeMainCatgCell: DatasourceCell { 
    weak var delegate:HomeMainCatgCellDelegate? 
    //Remove the variable var homeViewcontroller: HomeViewController? to avoid reference cycle and we don't need it anyway. 
... 
func handleClickCtg(gestureRecognizer: UITapGestureRecognizer) { 
    guard let tag = gestureRecognizer.view?.tag else {return} 
    print(tag) 
    if let clickedImageView = CategoryViews(rawValue:tag){ 
     self.delegate?.clicked(view:clickedImageView,forCell:self) 
    } 
} 
} 

Ensuite, dans votre classe de contrôleurs de vue, vous pouvez confirmer le protocole HomeMainCatgCellDelegate et définir le délégué de la cellule sur self.

class HomeViewController: DatasourceController, HomeMainCatgCellDelegate{ 
... 
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
//Dequeue your cell here 
cell.delegate = self 
... 
return self 
} 
func clicked(view:CategoryViews,forCell cell:HomeMainCatgCell){ 
    //And you can handle your events accordingly here 
    if let indexpath = self.collectionView.indexPath(for: cell){ 
    //Here you will get the indexpath of clicked cell and then you can put a switch condition to check which imageview is clicked 
      switch view{ 
      case .personal:break 
      case .healthcare:break 
      case .homecare:break 
      case .kitchencare:break 
      } 
    } 
} 
} 

Espérons que cela aide.

+0

merci @nishith –

+0

J'ai besoin d'une aide supplémentaire si j'utilise collectionView au lieu de imageViews puis ce que je fais ... ?? une idée –

+1

Vous pouvez consulter cette bibliothèque pour obtenir de l'aide https://github.com/DahanHu/DHCollectionTableView –

1

Le problème est que votre variable « homeViewcontroller » est pas configuré correctement.

Ce code:

var homeViewcontroller = HomeViewController() 

Crée une instance d'une classe HomeViewController. Mais cette instance n'est aucunement liée à l'écran que vous pensez être. L'écran qui présente votre vue actuelle est une instance complètement différente. Pour être honnête, la façon dont vous enchaînez tout est assez bizarre et ce n'est pas très intuitif. Mais si vous voulez résoudre votre problème sans trop modifier votre code, vous devez passer le REAL HomeViewController vers le bas.

donc sur le HomeViewController.swift vous avez ce code:

let homeViewDatasource = HomeViewDatasource() 
self.datasource = homeViewDatasource 

passer le "handleCtgClick" comme fermeture.

Quelque chose comme

homeViewDataSource.presenterClosure = {(ctgname: String ,ctgId: String) in 
     let dummySettingViewController = UIViewController() 
     dummySettingViewController.view.backgroundColor = UIColor.white 
     dummySettingViewController.navigationItem.title = ctgname 
     navigationController?.navigationBar.tintColor = UIColor.white 
     navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white] 
     navigationController?.pushViewController(dummySettingViewController, animated: true) 
} 

(Notez que vous devez créer cette fermeture déclaration de variable au sein de votre HomeViewDatasource.swift afin que vous pouvez l'affecter de la HomeViewController.rapide)

Ensuite, répétez cette étape à nouveau passer à la HomeMainCatgCell.swift

Ensuite, vous serez en mesure d'appeler cette fonction faisant référence à la variable de fermeture locale créée.

ALTERNATIVE:

Vous pouvez tout simplement passer la référence à la HomeViewController lui-même. Mais si vous décidez de le faire, assurez-vous de continuer à le passer comme une variable "optionnelle" avec une propriété "faible" ou vous créerez une boucle de retenue.

+0

Monsieur pouvez-vous s'il vous plaît fournir un exemple pour moi. En fait, je ne comprends pas bien votre point. –