2016-10-04 36 views
1

我在可重用的標題視圖中有一個按鈕,用於刪除爲集合視圖和標題提供數據的數組中的信息。我希望它也能夠執行collectionView.reloadData()如何從可重用標題按鈕調用collectionView.reloadData()?

問題是我不能從標題按鈕調用collectionView.reloadData(),因爲它不能將collectionView識別爲變量。如果我打電話Builds().collectionView.reloadData()(構建是視圖控制器),該應用程序崩潰,因爲它說它發現零,而解包可選。我知道,簡單地叫collectionView.reloadData()不是問題,因爲我有collectionView.reloadData()調用viewDidAppear(),並且這不會導致崩潰。

這是怎麼回事?如何在按鈕刪除數據後讓我的collectionView重新加載數據?

參考:

可重複使用的部首:

import UIKit 

class BuildsHeader: UICollectionReusableView { 

@IBOutlet weak var headerLabel: UILabel! 

@IBOutlet weak var deleteBuildButton: UIButton! 

@IBAction func deleteBuildButton(sender: UIButton) { 

    for hero in heroes{ if hero.hero.name == heroForDetails.hero.name { 
     hero.builds.removeAtIndex(sender.tag) 
     heroForDetails = hero 
     }} 

    saveToDefaults(userProfile) 
    //Builds().collectionBuild.reloadData() runs just fine without this line 
} 
} 

的ViewController:

import UIKit 

class Builds: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { 

@IBOutlet weak var collectionBuild: UICollectionView! 

override func viewDidLoad() { 
    super.viewDidLoad() 

    collectionBuild.delegate = self 
    collectionBuild.dataSource = self 

} 

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

override func viewDidAppear(animated: Bool) { 
    collectionBuild.reloadData() 
} 

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 

     if let cell = collectionView.dequeueReusableCellWithReuseIdentifier("BuildCell", forIndexPath: indexPath) as? TalentsCell { 

      let build = heroForDetails.builds[indexPath.section] 

      switch (indexPath.row) { 

      case 0: 
       cell.configureCell(build["1"]! as! Talent) 
      case 1: 
       cell.configureCell(build["4"]! as! Talent) 
      case 2: 
       cell.configureCell(build["7"]! as! Talent) 
      case 3: 
       cell.configureCell(build["10"]! as! Talent) 
      case 4: 
       cell.configureCell(build["13"]! as! Talent) 
      case 5: 
       cell.configureCell(build["16"]! as! Talent) 
      case 6: 
       cell.configureCell(build["20"]! as! Talent) 
      default: 
       cell.configureCell(build["1"]! as! Talent) 

      } 

      return cell 

    } 
    return UICollectionViewCell() 
} 

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { 

} 

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
    return 7 
} 

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { 
    return heroForDetails.builds.count 
} 

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { 
    return CGSizeMake(50,50) 
} 

func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView { 

    let header = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "BuildsHeader", forIndexPath: indexPath) as! BuildsHeader 

    var buildDict = heroForDetails.builds[indexPath.section] 
    header.headerLabel.text = buildDict["name"] as! String 
    header.deleteBuildButton.tag = indexPath.section 
    return header 

} 
} 

enter image description here

+0

你可以委託做。 –

+0

@Sam_M真的是唯一的方法嗎?我必須爲通常需要1行代碼的東西添加一堆代碼行。另外,我已閱讀了有關授權但從未成功執行的授權。 – Apple

+0

爲每個部分有一個按鈕 –

回答

1

可以實現與代表團。

  1. 創建一個協議
  2. BuildsHeader爲委託創建一個變量
  3. 呼叫在deleteBuildButton功能

現在的委託方法BuildsHeader的代碼應該是這樣的:

import UIKit 

//**** The Protocol **** 
protocol BuildsHeaderDelegate { 
    func updateCollectionView() 
} 

class BuildsHeader: UICollectionReusableView { 

    //**** Variable for the delegate **** 
    var delegate: BuildsHeaderDelegate? 

    @IBOutlet weak var headerLabel: UILabel! 

    @IBOutlet weak var deleteBuildButton: UIButton! 

    @IBAction func deleteBuildButton(sender: UIButton) { 

     for hero in heroes{ if hero.hero.name == heroForDetails.hero.name { 
      hero.builds.removeAtIndex(sender.tag) 
      heroForDetails = hero 
      }} 

     saveToDefaults(userProfile) 
     //**** Call the delegate method **** 
     self.delegate?.updateCollectionView() 
    } 
} 
  1. 在您的收藏鑑於viewForSupplementaryElementOfKind方法配置頭的delegate財產,像這樣:

    let header = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "BuildsHeader", forIndexPath: indexPath) as! BuildsHeader 
    //**** Set this view controller to be the header's delegate **** 
    header.delegate = self 
    // rest of header setup 
    
  2. 充分利用Builds ViewController中確認到BuildsHeaderDelegate

    class Builds: UIViewController, BuildsHeaderDelegate, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { 
    
  3. 實施BuildsHeaderDelegate的委託方法在Builds視圖控制器中。您可以在viewForSupplementaryElementOfKind方法後,把這個權利:

    func updateCollectionView() { 
        //**** reload the collectionView **** 
        self.collectionBuild.reloadData() 
    } 
    
+0

偉大的工作!非常感謝。你或其他人能否解釋爲什麼我必須使用委派來完成這項工作?當標題和視圖控制器相互交談時,什麼是斷開連接?這將有助於我理解將來何時使用它。 – Apple

+0

@Apple委託在您想要在對象之間傳遞信息時非常有用。您無法訪問BuildsHeader類中的collectionView,並且無法重新加載它,因此您會向Builds viewController發送消息並告訴它重新加載collectionView。 –

+0

@蘋果谷歌「[ios代表團解釋](https://www.google.com/#q=ios+delegation+explained)」並閱讀更多內容。關於何時使用它的一個例子是你的[上一個問題](http://stackoverflow.com/questions/39647005/how-to-segue-from-child-view-controller-header-and-stay-within-parent-導航),這可以通過委派來解決。 –

1

使用d elegate要調用的方法:

protocol BuildsHeaderDelegate(){ 
    func reloadCollectionView() 
} 

class BuildsHeader: UICollectionReusableView { 

    var delegate:BuildsHeaderDelegate! 

    @IBOutlet weak var headerLabel: UILabel! 
    @IBOutlet weak var deleteBuildButton: UIButton! 

    @IBAction func deleteBuildButton(sender: UIButton) { 

     for hero in heroes{ if hero.hero.name == heroForDetails.hero.name { 
      hero.builds.removeAtIndex(sender.tag) 
      heroForDetails = hero 
      }} 

     saveToDefaults(userProfile) 

     //##Call delegate method## 
     delegate.reloadCollectionView() 
    } 

} 

順應代表在視圖控制器,併爲其分配:

class Builds: UIViewController,delegate:BuildsHeaderDelegate , UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { 

    @IBOutlet weak var collectionBuild: UICollectionView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     collectionBuild.delegate = self 
     collectionBuild.dataSource = self 

    } 

    func reloadCollectionView() { 
     collectionBuild.reloadData() 
    } 

    func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView { 

     let header = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "BuildsHeader", forIndexPath: indexPath) as! BuildsHeader 

     //##Assign Delegate## 
     header.delegate = self 

     var buildDict = heroForDetails.builds[indexPath.section] 
     header.headerLabel.text = buildDict["name"] as! String 
     header.deleteBuildButton.tag = indexPath.section 
     return header 

    } 

} 
+0

非常感謝。這個解決方案也有效。 – Apple

+0

這與公認的解決方案沒有區別。 :) –