item added to the array when I am using didSelectItemAt indexPath
and the array contains more than one element, but only one cell has the picture "Rectangle Filled"
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
indexSelected = indexPath.item
if trashButtonIsActive == true {
selectedItems.append(indexPath.item)
// I am adding indexPath.item to the array.Which need to compare with indexPath.item in cellForItemAt method.//
} else if trashButtonIsActive == false {
if selectedItems.count != 0 {
selectedItems.removeAll()
}
self.performSegue(withIdentifier: "cardView", sender: indexPath)
}
self.collectionView.reloadData()
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if trashButtonIsActive == true && selectedItems.count == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.labelText = array![indexPath.item].frontal
cell.buttonToTrash.setImage(UIImage(named: "Rectangle Empty"), for: .normal)
return cell
}else if trashButtonIsActive == true && selectedItems.count != 0 {
for index in selectedItems {
//I don't know why , but it compares only first element in the array //
if indexPath.item != index {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.labelText = array![indexPath.item].frontal
cell.buttonToTrash.setImage(UIImage(named: "Rectangle Empty"), for: .normal)
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.labelText = array![indexPath.item].frontal
cell.buttonToTrash.setImage(UIImage(named: "Rectangle Filled"), for: .normal)
return cell
}
}
}else if trashButtonIsActive == false {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.labelText = array![indexPath.item].frontal
cell.buttonToTrash.setImage(nil, for: .normal)
return cell
}
let cellTwo = collectionView.dequeueReusableCell(withReuseIdentifier: "cell hello", for: indexPath)
return cellTwo
}
I want indexPath.row's which are equal to the elements in the array to have the picture "Rectangle Filled". Would anyone be able to assist?
make your model like this
struct ModelName{
var name: String
var rectangle: Bool
}
then you array which is selected items will be like this
var selectedItems = [ModelName]()
then in viewdidload or anywhere you are trying to initialise data you can do this
selectedItems.apped(ModelName(name: "name", rectangle: false)
selectedItems.apped(ModelName(name: "new", rectangle: true)
selectedItems.apped(ModelName(name: "newname", rectangle: false)
selectedItems.apped(ModelName(name: "namename", rectangle: false)
etc
then for cellforrow at do this
let item = selectedItems[indexPath.item]
cell.textlabel.text = item.name
if item.rectangle == true{
cell.rectButton.setImage(UIImage(named: "rectangle", for: .normal)
}else{
cell.rectButton.setImage(nil, for: .normal)}
return cell
I have tried with just name and rectangle you can do whatever you want if you don't want to initialse with any value make that variable nil
Related
[ I want to use two custom cells in one UICollectionView and this is by far I have been trying and I am stuck. Cell one for first and row and cell two of the second row and again cell one for 3rd, you get the point.
here is the code ]
import UIKit
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var CV: UICollectionView!
let labelArray = ["one", "two", "three", "four"]
let imageArray = [UIImage(named: "one"), UIImage(named: "two"), UIImage(named: "three"), UIImage(named: "four") ]
override func viewDidLoad() {
super.viewDidLoad()
CV.delegate = self
CV.dataSource = self
CV.reloadData()
// let nibCellOne = UINib(nibName: "CVCellOne", bundle: nil)
// let nibCellTwo = UINib(nibName: "CVCellTwo", bundle: nil)
// CV.register(nibCellOne, forCellWithReuseIdentifier: "CVCellOne")
// CV.register(nibCellTwo, forCellWithReuseIdentifier: "CVCellTwo")
CV.register(CollectionViewCell.self, forCellWithReuseIdentifier: "CVCellOne")
CV.register(CollectionViewCell.self, forCellWithReuseIdentifier: "CVCellTwo")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.section == 0 {
let cell1 = collectionView.dequeueReusableCell(withReuseIdentifier: "CVCellOne", for: indexPath) as! CollectionViewCell
cell1.cellOneLabel.text = labelArray[indexPath.row]
return cell1
}
else if indexPath.section == 1 {
let cell2 = collectionView.dequeueReusableCell(withReuseIdentifier: "CVCellTwo", for: indexPath) as! CollectionViewCell
cell2.cellTwoLabel.text = labelArray[indexPath.row]
return cell2
} else if indexPath.section == 2 {
let cell1 = collectionView.dequeueReusableCell(withReuseIdentifier: "CVCellOne", for: indexPath) as! CollectionViewCell
cell1.cellOneImage.image = imageArray[indexPath.row]
cell1.cellOneLabel.text = labelArray[indexPath.row]
return cell1
} else {
let cell2 = collectionView.dequeueReusableCell(withReuseIdentifier: "CVCellTwo", for: indexPath) as! CollectionViewCell
cell2.cellTwoImage.image = imageArray[indexPath.row]
cell2.cellTwoLabel.text = labelArray[indexPath.row]
return cell2
}
}
}
This is the customCell xib file
If what you need is every even row to use Cell1, and every odd row to use Cell2, then don't check for the specific row, check for the remainder when you divide by 2 (modulus) indexPath.item % 2 == 0
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item % 2 == 0 {
let cell1 = collectionView.dequeueReusableCell(withReuseIdentifier: "CVCellOne", for: indexPath) as! CollectionViewCell
cell1.cellOneLabel.text = labelArray[indexPath.row]
return cell1
}
} else {
let cell2 = collectionView.dequeueReusableCell(withReuseIdentifier: "CVCellTwo", for: indexPath) as! CollectionViewCell
cell2.cellTwoLabel.text = labelArray[indexPath.row]
return cell1
}
}
}
Can you please help me to find a solution and not to copy the same code again and again? Now I do have this code
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: productImageCell, for: indexPath) as! ProductImageCell
if let product = self.product {
cell.product = product
}
cell.selectionStyle = .none
return cell
} else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: productDetailCell, for: indexPath) as! ProductDetailCell
cell.backgroundColor = UIColor.lightGray
if let product = self.product {
cell.product = product
}
cell.selectionStyle = .none
return cell
} else if indexPath.row == 2 {
let cell = tableView.dequeueReusableCell(withIdentifier: productDeliveryCell, for: indexPath) as! ProductDeliveryTimeCell
cell.selectionStyle = .none
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: productDeliveryCell, for: indexPath) as! ProductDeliveryTimeCell
cell.selectionStyle = .none
return cell
}
}
As you can see I do copy this part again and again
let cell = tableView.dequeueReusableCell(withIdentifier: productImageCell, for: indexPath) as! ProductImageCell
if let product = self.product {
cell.product = product
}
cell.selectionStyle = .none
return cell
I did try something like that but it is not working
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = UITableViewCell()
if indexPath.row == 0 {
cell = tableView.dequeueReusableCell(withIdentifier: productImageCell, for: indexPath) as! ProductImageCell
} else if indexPath.row == 1 {
cell = tableView.dequeueReusableCell(withIdentifier: productDetailCell, for: indexPath) as! ProductDetailCell
} else if indexPath.row == 2 {
cell = tableView.dequeueReusableCell(withIdentifier: productDeliveryCell, for: indexPath) as! ProductDeliveryTimeCell
} else {
cell = tableView.dequeueReusableCell(withIdentifier: productDeliveryCell, for: indexPath) as! ProductDeliveryTimeCell
}
if let product = self.product {
cell.product = product
}
cell.selectionStyle = .none
return cell
}
include product property in all cells. Remove indexpath.row == 2 block, it does nothing.
write code like this ,
if indexPath.row == 1 {
var cell = tableView.dequeueReusableCell(withIdentifier: productImageCell, for: indexPath) as! ProductImageCell
cell.product == "" //clear product field for reusing property
if let product = self.product {
cell.product = product
}
cell.selectionStyle = .none
return cell
} else if .....
//You need to use same class in multiple cell as like,
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell:HomeCell!
if homeArray[indexPath.row]["type"] == "1" {
cell = tableView.dequeueReusableCell(withIdentifier: "ProductTitleCell", for: indexPath) as! HomeCell
}
else if homeArray[indexPath.row]["type"] == "2" {
cell = tableView.dequeueReusableCell(withIdentifier: "ProductImageCell", for: indexPath) as! HomeCell
}
cell.lbl_Title_1.text = homeArray[indexPath.row]["product_name"]
if cell.tag == 2 {
cell.imageview_1.image = UIImage(named: homeArray[indexPath.row]["product_image"]!)
}
return cell
}
I have a collection view (CollectionViewController) with 3 cells (each cell has it's own class). In the first cell (TextCell) I have a text field and a button (nextButton). When I press the button I want to check if the text field is empty or not. If it's not empty, I want to switch to the second cell.
CollectionViewController:
let textCell = TextCell()
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: self.cellId, for: indexPath)
// TextCell
if indexPath.item == 0 {
let tCell = collectionView.dequeueReusableCell(withReuseIdentifier: textCellId, for: indexPath)
let nextButton = textCell.nextButton
nextButton.addTarget(self, action: #selector(handleNextButton), for: .touchUpInside)
return tCell
}
return cell
}
//Handle Action
#objc func handleNextButton() {
let text = textCell.TextField.text
if text?.isEmpty == false {
scrollToIndex(menuIndex: 1)
} else {
print("Text field is empty.")
}
}
The problem is that every time i check if the text field is empty or not, it say's it is empty although it's not.
To identify whether the UITextField inside UICollectionViewCell is empty or not, you need to pass index position when button is clicked. To pass index position you can use tag. By using tag you can get clicked index position. After getting position, you can access elements from current index position by using cellForItemAtIndexPath . You can find the particular index position UITextField is empty or not using the fetched cell reference
In Your cellForItemAt
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 0{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YOUR_CELL_IDENTIFIER", for: indexPath) as! YOUR_UICOLLECTIONVIEW_CELL
cell.nextBtn.tag = indexPath.item
cell.nextBtn.addTarget(self, action: #selector(handleNextButton(_:)), for: .touchUpInside)
return cell
} else {
///use your other cells here
}
}
In your ViewController
func handleNextButton(_ sender:UIButton){
let indexPath = IndexPath(item:sender.tag,section:0)
let cell = YOUR_COLLECTIONVIEW.cellForItem(at: indexPath) as! YOUR_UICOLLECTIONVIEW_CELL
if cell.txtFld.text == "" {
print("TextField is empty")
} else {
print("TextField not empty")
}
}
Hope this will help you
First - Remove the next line, It's not needed and is definitely wrong!
let textCell = TextCell()
Now replace your func with that:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// TextCell
if indexPath.item == 0 {
let tCell = collectionView.dequeueReusableCell(withReuseIdentifier: textCellId, for: indexPath) as! TextCell
let nextButton = tCell.nextButton
nextButton.addTarget(self, action: #selector(handleNextButton), for: .touchUpInside)
return tCell
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: self.cellId, for: indexPath)
return cell
}
And The Handler
//Handle Action
#objc func handleNextButton(sender: UIButton) {
let tCell = sender.superview as! TextCell
let text = tCell.TextField.text
if text?.isEmpty == false {
scrollToIndex(menuIndex: 1)
} else {
print("Text field is empty.")
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let dev = devices[indexPath.item]
if dev.cuid == "3011"{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LightViewCell", for: indexPath) as! LightViewCell
let visibility = self.getStatusFor(nodeID: dev.node_id!, endpoint: dev.end_point!, devicename: dev.device_name!)
if visibility.contains("0"){
cell.LigntIMG.image = #imageLiteral(resourceName: "bulb-off")
cell.LightName.text = dev.device_name
cell.status = 0
cell.index = indexPath
cell.controlCMDs = getControlCMDS(nodeID: dev.node_id!, endpoint: dev.end_point!)
cells.append(cell)
}else{
cell.LigntIMG.image = UIImage(named: dev.menu_id!)
cell.LightName.text = dev.device_name
cell.status = 1
cell.index = indexPath
cell.controlCMDs = getControlCMDS(nodeID: dev.node_id!, endpoint: dev.end_point!)
cells.append(cell)
}
return cell
}
else if dev.cuid == "3006"{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DimmerLightViewCell", for: indexPath) as! DimmerLightViewCell
return cell
}
return //
}
I am having two types of custom cells(LightViewCell/DimmerLightViewCell) based on the conditions i need to display any one of the two cells......
types
here i am not returning any value, ignore that error.....i need to know how to implement the the above requirement..
Thank you:)
The method must return the cell. You can try this code:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let dev = devices[indexPath.item]
if dev.cuid == "3011"{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LightViewCell", for: indexPath) as! LightViewCell
let visibility = self.getStatusFor(nodeID: dev.node_id!, endpoint: dev.end_point!, devicename: dev.device_name!)
if visibility.contains("0"){
cell.LigntIMG.image = #imageLiteral(resourceName: "bulb-off")
cell.LightName.text = dev.device_name
cell.status = 0
cell.index = indexPath
cell.controlCMDs = getControlCMDS(nodeID: dev.node_id!, endpoint: dev.end_point!)
cells.append(cell)
}else{
cell.LigntIMG.image = UIImage(named: dev.menu_id!)
cell.LightName.text = dev.device_name
cell.status = 1
cell.index = indexPath
cell.controlCMDs = getControlCMDS(nodeID: dev.node_id!, endpoint: dev.end_point!)
cells.append(cell)
}
return cell
} else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LightViewCell", for: indexPath) as! DimmerLightViewCell
return cell
}
return //
}
you can do it by simply by using your condition in cellForRowAtIndexPath
For Example
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if(indexPath.item > 0){
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LightViewCell", for: indexPath) as! LightViewCell
/*do setup here*/
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DimmerLightViewCell", for: indexPath) as! DimmerLightViewCell
/*do setup here*/
return cell
}
}
I don't exactly understand what is the problem that you are facing.
But, you can try the below code for returning cell according to the given conditions in your code:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let dev = devices[indexPath.item]
if dev.cuid == "3011"
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LightViewCell", for: indexPath) as! LightViewCell
let visibility = self.getStatusFor(nodeID: dev.node_id!, endpoint: dev.end_point!, devicename: dev.device_name!)
cell.status = visibility.contains("0") ? 0 : 1
cell.LigntIMG.image = visibility.contains("0") ? #imageLiteral(resourceName: "bulb-off") : UIImage(named: dev.menu_id!)
cell.LightName.text = dev.device_name
cell.index = indexPath
cell.controlCMDs = getControlCMDS(nodeID: dev.node_id!, endpoint: dev.end_point!)
cells.append(cell)
return cell
}
else if dev.cuid == "3006"
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DimmerLightViewCell", for: indexPath) as! DimmerLightViewCell
return cell
}
return UICollectionViewCell()
}
I want to delete cell from UICollectionview,when user touchUpInside(Button) to remove cell.
Here is my code:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! CollectionViewCell
cell.myLabel.text = self.items[indexPath.row]
cell.deleteBtn?.layer.setValue(indexPath.row, forKey: "Cdelete")
cell.deleteBtn?.addTarget(self, action: Selector(("deleteColor:")), for: UIControlEvents.touchUpInside)
cell.backgroundColor = UIColor.cyan // make cell more visible in our example project
return cell
}
func deleteColor(sender:UIButton) {
let i : Int = (sender.layer.value(forKey: "Cdelete")) as! Int
self.items.remove(at: i)
collectionView.reloadData()
}
Where i am doing wrong?
set tag for your deletebutton for fetch the current cell/ know the which cell you tapped
cell.deleteBtn?.tag = indexPath.row
cell.deleteBtn?.addTarget(self, action: #selector(yourVCName. deleteColor(_:)), for: .touchUpInside)
and call like
#IBAction func deleteColor(_ sender: UIButton){
print("Button pressed 👍 ")
// continue your work
var hitPoint = sender.convert(CGPoint.zero, to: yourCollectionViewName)
var hitIndex: IndexPath? = yourCollectionViewName.indexPathForRow(at: hitPoint)
self.items.remove(at: hitIndex.row)
self.yourCollectionViewName.performBatchUpdates({
self.yourCollectionViewName.deleteItems(at: [hitIndex])
}) { (finished) in
self.yourCollectionViewName.reloadItems(at: self.yourCollectionViewName.indexPathsForVisibleItems)
}
}