Trying to get my head around collection views, arrays, and dictionaries. I have a class named CollectionViewCell that contains a UIImageView outlet that I want images from an array to populate. The trouble is that I have different sections with different content so I created multiple arrays that store the images. With the present code I get an error saying the array index is out of range. Do I need to populate the different sections with a dictionary that separates the information with keys and values instead?
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as CollectionViewCell
// Configure the cell
cell.imageView.image = green[indexPath.row]
cell.imageView.image = blue[indexPath.row]
return cell
How can I name the different sections with headers that are populated from an array? names is my array of strings and HeaderView is a class containing an empty label. I also get an error using this code.
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let headerView =
collectionView.dequeueReusableSupplementaryViewOfKind(kind,
withReuseIdentifier: "HeaderView",
forIndexPath: indexPath)
as HeaderView
headerView.label.text = names[indexPath.row]
return headerView
default:
assert(false, "Unexpected element kind")
}
}
[edit]
The number of sections and number of items in section code:
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
//Return the number of sections
return 2
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//Return the number of items in the section
return green.count
}
So if there's a different number of items in blue section as opposed to green, do I include return blue.count as well in the numberOfItemsInSection function?
Since green and blue are supposed to populate different sections, you need to use one or the other conditionally depending on the section, ex:
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//Return the number of items in the section
if section == 0 {
return green.count
} else {
return blue.count
}
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as CollectionViewCell
// Configure the cell
if indexPath.section == 0 {
cell.imageView.image = green[indexPath.row]
} else {
cell.imageView.image = blue[indexPath.row]
}
return cell
}
In your current code, if blue is a shorter array than green, you can get the error you described, since the numberOfItemsInSection goes beyond blue's index.
The indexPath object encapsulates information not only about the row, but also about the section. So, if you are referring to the first element in the first section, the indexPath.row will be 0 and indexPath.section will be 0. If you are referring to the third element in the second section, indexPath.row will be 2 and indexPath.section will be 1 ... and so on. In this context, how would you define cellForRowAtIndexPathand numberOfItems methods? Here is the code:
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//Return the number of items in the section
if(section == 0) {
return green.count
} else if(section == 1) {
return red.count
}
}
tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!) {
//Reusable cell code
if(indexPath.section == 0) {
//green cell population
}
else if(indexPath.section == 1) {
//red cell population
}
}
Related
I have a double direction scrolling collectionView with 50 sections, 10 items per section and 3 showing cells per section and filling the collectionView with the same data array.
the problem is the collectionView duplicate data in every section and I want to show different data in appearing sections to the user.
Any help please!
this is my code:
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 50
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: contentCellIdentifier,
for: indexPath) as! UserCollectionCell
cell.userImageView.kf.setImage(with: URL.init(string: String().loadCorrectUrl(url:firebaseUsers[indexPath.row].image)))
cell.userNameLabel.text=firebaseUsers[indexPath.row].name
if(selectedIndexPaths.contains(indexPath) ){
cell.userBackgroudView.isHidden=false
}
else{
cell.userBackgroudView.isHidden=true
}
}
return cell
}
Implement prepareForReuse in UserCollectionCell and clear the imageView and label text to prevent showing duplicate data on scroll
class UserCollectionCell: UICollectionViewCell {
override func prepareForReuse() {
super.prepareForReuse()
self.userImageView.image = nil
self.userNameLabel.text = nil
}
}
Hope it helps
I have an app with 2 different arrays that usually have 2 different item counts. For some reason the first collection view is getting the item count of the second collection view unless I get rid of the second collection view.
My code:
<script src="https://pastebin.com/embed_js/NAtgb3kp"></script>
Steps:
1. say your collection are
var albumsViewCollectionView, songsViewCollectionView : UICollectionView!
Register the nib files for your 2 collectionviews
your collectionview datasource method
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionview == albumsViewCollectionView {
return albumCount
}
else if collectionview == songsViewCollectionView {
return songsCount
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == albumsViewCollectionView {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AlbumsViewCollectionView", for: indexPath) as! AlbumsViewCollectionView
return cell
}
else if collectionView == songsViewCollectionView {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SongsViewCollectionView", for: indexPath) as! SongsViewCollectionView
return cell
}
return UICollectionViewCell()
}
I have UICollectionView, I am downloading images and displaying them in the cells. My first cell is of screen width and contains a button, rest are the general cells. The application only deques the first 2 cells, There are supposed to be 3 cells.
My cellForItemAtIndexPath function:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.row == 0 {
print("yay")
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "UploadNewCell", for: indexPath) as! UploadNewCell
return cell
}else if indexPath.row > 0 {
let userImages = userposts[indexPath.row]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProfileCell", for: indexPath) as! ProfileCell
cell.fillCells(uid: uid!, userPost: userImages)
return cell
}else{
return ProfileCell()
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.row == 0 {
print("hellowold")
} else {
let selecteditem : String!
selecteditem = userposts[indexPath.row]
performSegue(withIdentifier: "lol", sender: selecteditem)
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return userposts.count
}
my view:
There are supposed to be 3 images down there in the cells, One of them is dequed in the first index.
I am out of Ideas, Any ideas on the solution?
let userImages = userposts[indexPath.row]
At this point in your code, indexPath.row is > 0.
Arrays are 0-based, so the first cell (indexPath.row == 1) is getting the second item in your array (user posts[1]), which is the second image you wanted.
I can think of a couple of simple changes:
Change the index you're accessing, such as:
let userImages = userposts[indexPath.row - 1]
Add 1 to your userposts.count value in numberOfItemsInSection:
Split your collectionView into having multiple sections, so the top cell (UploadNewCell) is section 0, and the bottom three ProfileCells are a second section: this allows you to check the indexPath.section, and assign directly from row:
let userImages = userposts[indexPath.row]
Note: I would actually advise further modifying the code for the second option to create an enum for SectionType. That allows you to perform a switch over the potential values, allowing you to avoid that nasty default implementation, and boosts the readability of your code.
I have a collection view with sections, when the user did click on a cell, I'm trying to mark the as selected or checked, and then react on the selected cells, but the error I have is:
each section has 12 cells, when I select the cell everything is good I can mark it as checked, but it marks also another cell, it mark cell every 5 cells, if I downgrade the cells per section to 5, everything is ok it marks only 1 cell.
this is my code:
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 12
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("videoCell", forIndexPath: indexPath) as! VideoCell
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! VideoCell
if cell.checked == true {
cell.uncheck()
}
else {
cell.check()
}
}
I have a custom dynamic cell on a collectionView created on IB which will be filled with data from an array.
I want to add a static cell on the same CollectionView IB. Is it possible that the static cell to be on the last object of Collection View, no matter what array length is from dynamic cell the static cell would be added as last object?
here is the code for doing this.. I tried this method... For dynamic cell and static cell...
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 2
}
// Retuens the number of sections in collectionview
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
if section == 0 {
return data.count
}else if section == 1{
return 1
}else {
return 0
}
}
// Data get's filled into UICollectionView
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
var cell : CollectionCell!// important step...
if indexPath.section == 0 {
cell = collectionView.dequeueReusableCellWithReuseIdentifier("collectionViewCell", forIndexPath: indexPath) as! CollectionCell
//do something inside this
}
else if indexPath.section == 1 {
cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! CollectionCell
//here the static cell...
}
return cell
}