2017-04-20 14 views
2

我們希望通過在cell collection內單擊項目(i.e ImageView)時替換主控制器來顯示另一個控制器。但是我們無法獲取主集合視圖,無法導航目標控制器。我們使用以下方法 -當點擊collectionView的單元格內的項目時如何導航另一個視圖控制器使用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!) 
    } 
} 

主要問題

首先是我沒有結合整個小區的點擊,我只希望到Bing點擊裏面的細胞ImageView的。所以,我結合GestureRecognizer圖像視圖一樣 -

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

Click事件而言工作正常,它通過print(tag)的打印標籤(加在圖像視圖)點擊函數中。但是當呼叫功能self.homeViewcontroller.handleCtgClick(ctgname: CtgName! ,ctgId: CtgId!)(功能存在於HomeViewcontroller類)。它不會改變視圖控制器。

我也調試handleCtgClick功能,我發現我得到HomeViewcontroller的對象是nil

由於事先

+0

你可以更具體地說明實際問題是什麼?你得到什麼錯誤?或最新錯誤? (人們不應該通過你的代碼來找出錯誤,你應該指出。) – Pochi

+0

你可以顯示'cellForItemAt'方法。 –

+0

確保ViewController嵌入在UINavigationController中。如果沒有,它不會推動ViewController。 – MacKa

回答

1

如果您在單元類中聲明瞭控制器的全局實例,將會創建一個引用循環並在您的應用程序中創建泄漏。你的單元格將對你的控制器有一個強烈的參考,你的控制器將有一個強大的引用到你的tableview,這反過來又保持了對單元格的強烈引用,其次你可能無法告訴被點擊單元格的索引路徑,如果你允許編輯。您可以嘗試以下方法來解決這兩個問題。

首先,在您的單元類中創建一個枚舉,並根據圖像視圖命名,以便您的控制器知道哪個圖像視圖被點擊,並且您也可以將它與您的標記鏈接起來。喜歡的東西:

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

然後像你的類創建一個協議:

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

然後在你的類中創建一個弱變量,並調用協議方法在動作處理程序方法

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

然後在你的視圖控制器類中,你必須確認HomeMainCatgCellDelegate協議並將單元格的委託設置爲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 
      } 
    } 
} 
} 

希望這會有所幫助。

+0

謝謝@nishith –

+0

我需要一個更多的幫助,如果我使用collectionView而不是imageViews然後我做什麼...?任何想法 –

+1

你可以看看這個圖書館的幫助https://github.com/DahanHu/DHCollectionTableView –

1

的問題是,你的「homeViewcontroller」變量設置不正確。

此代碼:

var homeViewcontroller = HomeViewController() 

創建HomeViewController類的實例。但是這個實例與你認爲的屏幕沒有任何關係。呈現您當前視圖的屏幕是完全不同的實例。

說實話,你鏈接所有東西的方式很奇怪,它不是很直觀。但是如果你想在不改變代碼的情況下解決你的問題,你必須向下傳遞REAL HomeViewController。

所以在HomeViewController.swift你有這樣的代碼:

let homeViewDatasource = HomeViewDatasource() 
self.datasource = homeViewDatasource 

通過 「handleCtgClick」 作爲一個封閉它。

喜歡的東西

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

(請注意,你有你的HomeViewDatasource.swift內創建這個封閉變量聲明,這樣就可以從HomeViewController分配給它。SWIFT)

然後再重複此步驟,將它傳遞給HomeMainCatgCell.swift

然後你就可以調用這個函數引用您創建的本地閉包變量。

或者:

您只需通過參照HomeViewController本身。但是如果你決定這麼做的話,確保你繼續把它作爲一個帶有「弱」屬性的「可選」變量來傳遞,否則你將創建一個保留循環。

+0

先生,請你給我舉個例子。其實我不明白你的意思。 –

相關問題