Images not displayed in collection view cell - ios

I have a collection view cell and inside there's an imageView. On it I display array of images using sd_setImage once loaded from firestore. In console I see all images which my app downloaded.
I use this code:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "newDetailCollectionCell", for: indexPath) as! NewDetailCollectionViewCell
cell.imageView.sd_setImage(with: URL(string: images[indexPath.item]))
return cell
}
When I use this code I can't see my images. But if I use the code below everything works fine.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "newDetailCollectionCell", for: indexPath) as! NewDetailCollectionViewCell
cell.imageView.sd_setImage(with: URL(string: images[indexPath.item]))
return cell
}

The problem is that you should be calling collectionView.reloadData() instead of tableView.reloadData() in your Dispatch.main.async {} Because in this situation the collectionView needs to update the dataSource. I Hope this helps.
DispatchQueue.main.async {
self.collectionView?.reloadData()
}

Related

How can I manage two different cells in numberofitemsinsection

I want to create a collectionView with two different cells. The first cell should be displayed one time and the second should be displayed as often as the array is large. The result should be something like in the image in the attached link. Here is also a example code for better understanding my problem. Thanks to everyone who helps me!!! 🙂
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
switch indexpath { // No indexpath in numberofitemsinsection!
case 0:
return 1 //display one time the first cell
default:
return images.count // display as often as the array is large the second cell
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
switch indexPath.row {
case 0:
let cell = imageCollectionView.dequeueReusableCell(withReuseIdentifier: "addImageCell", for: indexPath)
return cell
default:
let cell = imageCollectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath) as! ImageCell
cell.imageView.image = images[indexPath.row]
cell.delegate = self
cell.selectedAtIndex = indexPath
return cell
}
}
Here is the collectionView I want to create
You can achieve this inside cellForItemAt and you need to change numberOfItemsInSection like below:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// return 1 more than our data array (the extra one will be the "add item" cell)
return dataSourceArray.count + 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// if indexPath.item is less than data count, return a "Content" cell
if indexPath.item < dataSourceArray.count {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ContentCell", for: indexPath) as! ContentCell
// configure your ContentCell: cell. <attribute>
return cell
}
// past the end of the data count, so return an "Add Item" cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AddItemCell", for: indexPath) as! AddItemCell
// configure your AddCell: cell. <attribute>
return cell
}
For that you need to create a ContentCell and AddItemCell and also have a dataSourceArray to store all data you need.
Why don't you use this?
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1 + theArray.count
}

Handle moveItem(at:to:) delegate method when using UICollectionViewDiffableDataSource

I need to use moveItem(at:to:) delegate method in order to move my collection view cells.
When I implement the data source delegation methods it's working fine, but I need to set my data source as UICollectionViewDiffableDataSource and in this way the moveItem(at:to:) did not call.
Any solution to handle,
This way it's work when using delegations :
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CustomCell
cell.textLabel.text = "Some value"
return cell
}
override func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool {
true
}
override func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
print("OK")
}
set data source in this way is not work
func setupDataSource() {
dataSource = UICollectionViewDiffableDataSource<Section, Person>(collectionView: collectionView, cellProvider: {
(collectionView: UICollectionView, indexPath: IndexPath, person: Person) -> UICollectionViewCell? in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CustomCell
cell.textLabel.text = "Some text"
return cell
})
}
For custom behavior create a subclass of UICollectionViewDiffableDataSource and override the methods there.

How do I call for multiple reuse identifiers if I manually added cells in storyboard for collectionViewCells?

I am practicing some coding on collectionViews. However I like to work in Main.storyboard to see what I am working with visually. Unfortunately it appears that makes more work on my end when working in the viewController because this would have been much faster if done programmatically.
I am trying to call for multiple reuse identifiers for the collectionViewCell. However I only know how to call one cell. Now I am not getting any errors, I just do not know how to display all of the cells when I run the program.
Here is the code.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 6
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Fashion Cell 0", for: indexPath)
return cell
}
When I run the app I get this.
Please note, in Main.Storyboard I am add the cells manually.
Example:
Do in this way
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 6
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Fashion Cell 0", for: indexPath)
return cell
}
if indexPath.item == 1 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Fashion Cell 1”, for: indexPath)
return cell
}
//……
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Fashion Cell 0", for: indexPath)
return cell
}
Although you can use switch instead of if for better readability
You can not in this way.Create one array of your number of images and set it to collectionView. No need to more cell in storyboard.
let video:[UIImage] = ["","","",""]
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return video.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)as! yourcellfile
let image = video[indexPath.row]
cell.img.image = image
return cell
}
You can go this way. It's proper method to imaplement collectionview.

Updating a single cell in UICollectionView using Swift

I have a problem with updating a single cell when using a UICollectionView.
When I click on a label I want the label to change to the value of a different number which I can assign manually.
Code:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//return nameArray.count;
return 81;
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell=collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell;
switch(flattened[indexPath.item]){
case 1:
cell.labelText.text="1";
case 2:
cell.labelText.text="2";
case 3:
cell.labelText.text="3";
case 4:
cell.labelText.text="4";
case 5:
cell.labelText.text="5";
case 6:
cell.labelText.text="6";
case 7:
cell.labelText.text="7";
case 8:
cell.labelText.text="8";
case 9:
cell.labelText.text="9";
default:
cell.labelText.text="0";
//print(indexPath.item)
}
return cell;
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
When I run my code:
Firstly add those values in array
var array:[String] = ["1", "2" ,"3"] //and so on
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return array.count
}
and in cellforRow do like this
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
cell.label.text = self.array[indexpath.row]
}
Use collection view didSelectItem to get a particular cell you will tap
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.array[indexpath.row] = "YOUR VALUE"
//self.collectionView.reloadData()
self.collectionView.reloadItems(at: [indexpath])
}
SUGGESTION: Try to learn about MVC, MVVM and modelling
and then try like this way: https://stackoverflow.com/a/49248513/5589073

Multiple selections on collection view cells

I am trying to make an app with similar functionality to the Photos app that comes with iOS, I have the functionality that allows you to tap on a cell which expands the image to fit the screen, then tap the image to dismiss it. I now want to add the select button so that you can select multiple images that can be downloaded. I'm fairly new to this and have looked around but can't find an example that does both of these things. Any help would be great.
Update:
My current code:
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imagesURLArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath) as! PhotoCell
cell.backgroundColor = .clear
cell.imageView.image = UIImage(contentsOfFile: imagesURLArray[indexPath.row].path)
cell.checkmarkView.isHidden = true
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,sizeForItemAt indexPath: IndexPath) -> CGSize {
let paddingSpace = sectionInsets.left * (itemsPerRow + 1)
let availableWidth = view.frame.width - paddingSpace
let widthPerItem = availableWidth / itemsPerRow
return CGSize(width: widthPerItem, height: widthPerItem)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,insetForSectionAt section: Int) -> UIEdgeInsets {
return sectionInsets
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return sectionInsets.left
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
addZoomedImage(indexPath.row)
addGestureToImage()
addBackGroundView()
view.addSubview(selectedImage)
}
Im not sure whereto go from here, whether its easier to add long tap gestures to select multiple images to download or to have the select button in the photos app both of which im a little clueless on where to start.
OK - one approach:
Design a custom button (or find one already made) that provides "CheckMark" functionality (tap to check/uncheck)
Add that button to your PhotoCell - maybe upper-left or upper-right corner
When the cell is tapped on the CheckMark button, toggle it checked/unchecked and send a message back to your controller to track its state
If the cell is tapped but not on the checkmark button, handle it as you do now with didSelectItemAt indexPath:
That's the general idea. A good next place for you is probably to take a look at some examples found by searching for uicollectionviewcell check mark
//works in swift 3.3 Hope it helps
//my model struct
struct Brands {
var brandId: Int = 0
var productId: Int = 0
var name: String = ""
var isChecked:Bool = false
}
var arrBrands = []//initialise arr of model
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return arrBrands.count
}
func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let identifier: String = "brandCell"
let cell: YourCustomCell? =
collectionView.dequeueReusableCell(withReuseIdentifier: identifier,
for: indexPath) as? YourCustomCell;
let isChecked = arrBrands[indexPath.row].isChecked
cell?.brandName.font = (isChecked) ?fontForTimesRoman(withStyle:"bold", andFontsize: 14):fontForTimesRoman(withStyle: "regular",
andFontsize: 14)
cell?.brandName.text = arrBrands[indexPath.row].name
cell?.brandCheckButt.setImage((isChecked) ?UIImage(named:"filled_checkmark.png"):UIImage(named:"empty_checkmark.png"), for: .normal)
return cell!
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
checkUncheckBrand(index: indexPath.row)
}
func collectionView(_ collectionView: UICollectionView,
didDeselectItemAt indexPath: IndexPath) {
checkUncheckBrand(index: indexPath.row)
}
func checkUncheckBrand(index:Int){
arrBrands[index].isChecked = ! (arrBrands.isChecked)
brandFilterCV.reloadData()
}

Resources