2016-10-29 40 views
0

問:如何通過按鈕將UICollectionViewCell轉換爲另一個ViewController?

如何過渡UICollectionViewCell我分配了一個按鈕上UICollection到另一個視圖控制器?

摘要:

  1. 我創建了一個UICollection,並UICollectionCells爲每個圖像我有。
  2. 我爲每個找到的圖像創建一個CollectionCell對象。
  3. 我可以爲每個對象創建圖像和按鈕,但是一旦我設置了單元格按鈕的目標,我就無法重定向到另一個ViewController。

嘗試:

我看了一些其他的嘗試,但都需要將功能從原來的視圖控制器調用。

開始從當前視圖控制器內的視圖控制器:

let secondViewController:SecondViewController = SecondViewController() 

    self.presentViewController(secondViewController, animated: true, completion: nil) 
} 

調用從視圖控制器的函數:

button.addTarget(self,action:#selector(YourControllerName.buttonClicked(_:)), 
         forControlEvents:.TouchUpInside) 

當前代碼:

class CollectionViewCell: UICollectionViewCell { 
    var text: String! 
    var image_view: UIImageView! 
    var button: UIButton! 

    override func awakeFromNib() { 
     print("Number:" + card_text) 

     image_view = UIImageView(frame: contentView.frame) 
     image_view.contentMode = .scaleAspectFill 
     mage_view.clipsToBounds = true 
     contentView.addSubview(image_view) 

     let x_value = contentView.frame.width - contentView.frame.width 
     let y_value = (contentView.frame.height)/3 
     let rectangle = CGRect(x: x_value, y: y_value, width: contentView.frame.width, height: 40) 
     button = UIButton(frame: rectangle) 
     button.backgroundColor = UIColor.darkGray 
     button.setTitle(card_text, for: .normal) 
     button.layer.cornerRadius = 3 
     button.clipsToBounds = true 
     button.addTarget(self,action: #selector(ObjectViewCell.buttonPressed), for: .touchUpInside) 
     contentView.addSubview(button) 
    } 

    func buttonPressed(sender:UIButton!) { 
     print("Practicing: " + self.card_text) 
    } 
} 






class Selector: UIViewController 
{ 
    var collectionView: UICollectionView! 
    let base_image = UIImage(named: "blank") 
    var images = [UIImage(named: "blank"), UIImage(named: "blank"), UIImage(named: "blank"), UIImage(named: "blank"), UIImage(named: "blank"), UIImage(named: "blank"), UIImage(named: "blank"), UIImage(named: "blank"), UIImage(named: "blank"), UIImage(named: "blank"), UIImage(named: "blank"), UIImage(named: "blank")] 

    @IBOutlet weak var main_view: UIView! 


    override func viewDidLoad() { 
     super.viewDidLoad() 
     print("Loading view in Selector") 
     setupCollectionView() 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    func setupCollectionView() { 
     let layout = UICollectionViewFlowLayout() 

     // Add spacing around each cell. 
     layout.minimumLineSpacing = 10 
     layout.minimumInteritemSpacing = 10 

     // Set each cell size to the size of the image. 
     layout.estimatedItemSize = CGSize(width: (base_image?.size.width)!, height: (base_image?.size.height)!) 

     // Set the collection view to the size of the view frame. 
     collectionView = UICollectionView(frame: main_view.frame, collectionViewLayout: layout) 

     // Register all images with the CollectionViewCell object. 
     collectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: "cell") 

     // Set the background color. 
     collectionView.backgroundColor = UIColor.white 
     collectionView.delegate = self 
     collectionView.dataSource = self 

     // Add the collections view to the main view. 
     view.addSubview(collectionView) 
    } 
} 


extension Selector: UICollectionViewDelegate, UICollectionViewDataSource 
{ 
    func numberOfSections(in collectionView: UICollectionView) -> Int { 
     return 1 
    } 

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     return images.count 
    } 

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 

     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell 
     cell.card_text = String(indexPath.item + 1) 
     cell.awakeFromNib() 
     return cell 
    } 

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { 
     let cardCell = cell as! ObjectViewCell 
     cardCell.image_view.image = images[indexPath.row] 
    } 

更新:

這裏是我落得這樣做。我閱讀了所有人的評論和答案,並且決定在發起UICollection單元的視圖控制器中進行所有必要的更改。因此,我將我的邏輯移出了CollectionViewCell對象,而是在單元的初始化中添加了所有邏輯/子視圖。

現在我只需要弄清楚如何轉換視圖控制器。謝謝大家。

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) 
     let contentView = cell.contentView 
     let image_view = UIImageView(image: base_image) 

     image_view.contentMode = .scaleAspectFill 
     image_view.clipsToBounds = true 
     contentView.addSubview(image_view) 

     let x_value = contentView.frame.width - contentView.frame.width 
     let y_value = (contentView.frame.height)/3 
     let rectangle = CGRect(x: x_value, y: y_value, width: contentView.frame.width, height: 40) 
     let button = UIButton(frame: rectangle) 

     let text = String(indexPath.item + 1) 
     button.setTitle(text, for: .normal) 
     button.accessibilityHint = text 
     button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside) 
     contentView.addSubview(button) 
     return cell 
    } 



func buttonPressed(sender:UIButton!) { 
     print("Button pressed") 
     print(sender.accessibilityHint) 

     //let navController = UINavigationController(rootViewController: self) 
     // 2. Present the navigation controller 
     //self.present(navController, animated: true, completion: nil) 
    } 
+0

問題是你的'buttonPressed'不能做任何事情。 – matt

+0

我知道!因爲我移除了嘗試轉換到另一個視圖控制器。我收到編譯錯誤。 – Speakeasys

+0

你不應該自己調用'awakeFromNib';這將導致您的單元在重用時獲得多個子視圖。你需要在你的單元格中保留一個引用現有文本字段的屬性,並在更改文本屬性時更新該屬性,使用setter – Paulw11

回答

1

的問題是,你的按鈕的對象是細胞,所以buttonPressed動作功能位於細胞。這是一件非常愚蠢的事情,因爲(正如你所說的),如果沒有視圖控制器發送它,你不能調用present

我會做的是設置按鈕的目標/選擇器在cellForItemAt:。這樣,self的視圖控制器,我們可以將目標設置爲self。但你沒有那樣做!

因此,您需要從單元獲取控制它的視圖控制器。

但是,有一種方法。這叫做行走響應者鏈。一個UIResponder變量設置爲按鈕:

var responder : UIResponder = self 

現在循環,呼籲respondernext走一步了鏈:

responder = responder.next 

每一次,看看是否這個應答是一個UIViewController。當它是,停止循環併發送它present!因此:

var responder : UIResponder = self 
repeat { responder = responder .next } while !(responder is UIViewController) 
let vc = responder as! UIViewController 
vc.present(// ... 

(不過,即使這個問題可以通過這種方式來解決,我認爲這是愚蠢的,讓自己陷入這個爛攤子擺在首位使得視圖控制器的目標首先會。在我看來,這已經是一個更好的主意了。)

+0

我不是這些解決方案的粉絲。 1)正確的封裝決定了ViewController不會通過CollectionViewCell的屬性來泛化,2)沿着響應者鏈尋找你的父視圖控制器是超級黑客行爲。使用委託模式;它的每個人都期望在可可。單元格指出用戶如何導航到細節視圖的細節,並告訴ViewController和ViewController執行該操作。兩者鬆散耦合並保持關注點的分離,ViewController對按鈕按下詳細信息一無所知。 –

+0

@JoshHomann我明白你在說什麼了。我正在討論的方式是繞過MVC。相反,我應該允許視圖控制器控制轉換,而不是試圖允許單元格確定該邏輯。你碰巧知道我怎麼這樣做?理想情況下,我想根據他們按下哪個按鈕將用戶轉到其他視圖。它可能是一個只有一個參數的視圖。 – Speakeasys

+0

@JoshHomann我完全不同意!細胞是視野,純淨和簡單。視圖控制器是控制器;應該做這個想法。而且視圖控制器_qua_數據源肯定是_does_,通過單元格的屬性來渲染;這是_Exactly_它的作用。 – matt

相關問題