2016-11-23 47 views
1

我最近開始使用Swift,並試圖從頁面上的一個UICollectionView(工作)到兩個其中。我收到錯誤對於多個UICollectionView,出現錯誤,「...必須用非零布局進行初始化」

「終止應用程序由於未捕獲的異常‘NSInvalidArgumentException’的,理由是:‘UICollectionView必須以非空佈局參數初始化’」。

什麼我迄今發現的堆棧溢出已納入我的代碼,但我仍然得到錯誤。我在智慧的結尾,請幫助!

我去過的地方:

  • 我開始與this article上建立UICollectionView,一切工作就好了。
  • 現在要在同一屏幕上設置第二個UICollectionView,我按照this article中的說明操作。
  • 似乎一切都還好,我得到「打造成功」,隨後立即進行崩潰的應用程序開始運行。錯誤消息說:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter'

  • 尋找在StackOverflow上的錯誤,我發現this article(與單UICollectionView交易,而不是兩個,我有)。
  • 我實現了我所能那篇文章,但我仍然得到錯誤,而現在的想法。我的代碼如下,任何幫助將非常感謝!

ViewController.swift

import UIKit 
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate { 

var collectionViewLeft = UICollectionView()       // changed "let" to "var" so I can assign things to it in viewDidLoad() 
var collectionViewRight = UICollectionView() 
let collectionViewLeftIdentifier = "CollectionViewLeftCell" 
let collectionViewRightIdentifier = "CollectionViewRightCell" 

override func viewDidLoad() { 

    super.viewDidLoad() 

    let layoutLeft = UICollectionViewFlowLayout()     // this is what **I would think** would be my non-nil layout 
    layoutLeft.itemSize = CGSize(width: 100, height: 100) 

    let layoutRight = UICollectionViewFlowLayout() 
    layoutRight.itemSize = CGSize(width: 100, height: 100) 

    collectionViewLeft = UICollectionView(frame: self.view.frame, collectionViewLayout: layoutLeft) 
    collectionViewRight = UICollectionView(frame: self.view.frame, collectionViewLayout: layoutRight) 

    collectionViewLeft.delegate = self 
    collectionViewRight.delegate = self 

    collectionViewLeft.dataSource = self 
    collectionViewRight.dataSource = self 

    self.view.addSubview(collectionViewLeft) 
    self.view.addSubview(collectionViewRight) 

    collectionViewLeft.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewLeftIdentifier) 
    collectionViewRight.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewRightIdentifier) 

} 


let reuseIdentifierLeft = "cellLeft" // also enter this string as the cell identifier in the storyboard 
let reuseIdentifierRight = "cellRight" 

var itemsRight = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"] 
var itemsLeft = ["10", "20", "30", "40", "50", "60"] 


// MARK: - UICollectionViewDataSource protocol 

// tell the collection view how many cells to make 
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 

    if collectionView == self.collectionViewLeft { 
      return self.itemsLeft.count 

    } else if collectionView == self.collectionViewRight { 
      return self.itemsRight.count 
    } else { 
     print("This is very bad") 
     assert(false, "Passed collectionView is neither collectionViewLeft nor collectionViewRight -- ruh roh!") 
     return 0 
    } 
} 

// make a cell for each cell index path 
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 

    if collectionView == self.collectionViewLeft { 
     // get a reference to our storyboard cell 
     let cellLeft = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifierLeft, for: indexPath as IndexPath) as! MyCollectionViewCell 

     // Use the outlet in our custom class to get a reference to the UILabel in the cell 
     cellLeft.myLeftLabel.text = self.itemsLeft[indexPath.item] 
     cellLeft.backgroundColor = UIColor.red // make cell more visible in our example project 

     return cellLeft 
    } else if collectionView == self.collectionViewRight { 
     let cellRight = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifierRight, for: indexPath as IndexPath) as! MyRightCollectionViewCell 

     // Use the outlet in our custom class to get a reference to the UILabel in the cell 
     cellRight.myRightLabel.text = self.itemsRight[indexPath.item] 
     cellRight.backgroundColor = UIColor.green // make cell more visible in our example project 

     return cellRight 
    } else { 
     print("This is very bad") 
     assert(false, "Passed collectionView is neither collectionViewLeft nor collectionViewRight -- ruh roh!") 

     // won't actually execute the following, but to keep the compiler happy... 
     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifierLeft, for: indexPath as IndexPath) as! MyCollectionViewCell 
     return cell 
    } 
} 

// MARK: - UICollectionViewDelegate protocol 

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 

    // handle tap events 

    if collectionView == self.collectionViewLeft { 
     print("You tapped cell #\(indexPath.item) on the LEFT!") 
    } else if collectionView == self.collectionViewRight { 
     print("You tapped cell #\(indexPath.item) on the RIGHT!") 
    } else { 
     print("This is very bad") 
     assert(false, "Passed collectionView is neither collectionViewLeft nor collectionViewRight -- ruh roh!") 
    } 
} 

}

MyCollectionViewCell.swift

import UIKit 

class MyCollectionViewCell: UICollectionViewCell { 

    @IBOutlet weak var myLeftLabel: UILabel! 

} 

class MyRightCollectionViewCell: UICollectionViewCell { 

    @IBOutlet weak var myRightLabel: UILabel! 

} 

回答

3

我的猜測,你聲明UICollectionViewController的空默認init構造函數和變量:

var collectionViewLeft = UICollectionView() 
var collectionViewRight = UICollectionView() 

嘗試更換您的變量聲明不構造函數:下面

編輯的代碼:作爲@ Paulw11正確地在下面他的回答指出,最好是使用隱含展開OPTIO最後!而不是 ?

var collectionViewLeft: UICollectionView! 
var collectionViewRight: UICollectionView! 

無論如何,你都實例化它們在你的viewDidLoad功能與UICollectionView指定initialisers。

只是說明一下,最好在UICollectionView作爲子視圖添加之前註冊自定義類/ xib。現在並不重要,但在重構&等之後可能會出現問題,因爲在爲單元註冊自定義類代碼之前,您的代碼可以調用UICollectionViewdelegatedataSource函數。只是通話將您的代碼.register()以上self.view.addSubview()

collectionViewLeft.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewLeftIdentifier) 
collectionViewRight.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewRightIdentifier) 
+0

非常好 - 謝謝!我的代表不足以支持投票計數(但?),但這似乎奏效了。 – ConfusionTowers

+0

不用擔心投票,我們大多數人都在這裏只是爲了幫助。編程祝你好運! – dive

+2

我建議你使用隱式解包可選!而不是 ?否則你必須不斷解開觀點。如果觀點*爲*無,那麼這是一個嚴重的問題,並且沒有合理的方法可以繼續。 – Paulw11

3

不分配空UICollectionView對象的屬性;你只是反正把它們扔掉,它導致了異常,因爲你沒有提供的佈局。這是一個情況下,你可以使用一個隱含展開可選:

var collectionViewLeft: UICollectionView!       
var collectionViewRight: UICollectionView! 
+0

後續問題發佈[這裏](http://stackoverflow.com/questions/40776822/error-implementing-a-2nd-uicollectionview-could-not-出列-A-視圖的實物-UIC)。同樣的項目,新的錯誤。 – ConfusionTowers

相關問題