Selector to get indexPath UICollectionView Swift 3.0
First of all you are adding tapGesture to collectionView
instead of subOptioncell
.
It should be:
subOptioncell.addGestureRecognizer(tap)
Instead of:
collectionView.addGestureRecognizer(tap)
You cannot pass other instance with selector
of UIGestureRecognizer
, the only instance you can pass is UI(Tap)GestureRecognizer
. If you want the indexPath of that cell you can try like this. First of all set your selector
of TapGesture
like this.
let tap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped(sender:)))
Now method should be like:
func doubleTapped(sender: UITapGestureRecognizer) {
if let cell = sender.view as? SubOptionsCollectionViewCell, let indexPath = self.collectionView.indexPath(for: cell) {
print(indexPath)
}
}
Edit: If you want to show/hide image on cell double tap then you need to handle it using indexPath
of cell, for that first declare one instance of IndexPath
and use it inside cellForItemAt indexPath
.
var selectedIndexPaths = IndexPath()
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//Your code
//Now add below code to handle show/hide image
cell.subOptionSelected.isHidden = self.selectedIndexPaths != indexPath
return cell
}
Now on doubleTapped
action of UITapGestureRecognizer
set the selectedIndexPath
.
func doubleTapped(sender: UITapGestureRecognizer) {
if let cell = sender.view as? SubOptionsCollectionViewCell, let indexPath = self.collectionView.indexPath(for: cell) {
if self.selectedIndexPaths == indexPath {
cell.subOptionSelected.isHidden = true
self.selectedIndexPaths = IndexPath()
}
else {
cell.subOptionSelected.isHidden = false
self.selectedIndexPaths = indexPath
}
}
}
Get IndexPath of CollectionViewCell outside of Cell
Get the location of the tapGestureRecognizer
in the collectionView
and then the indexPath
at the given location
let pointInCollectionView = tapGestureRecognizer.location(in: collectionView)
let indexPath = collectionView.indexPathForItem(at: pointInCollectionView)
Swift 5 CollectionView get indexPath by longPress cell
Start by getting the coordinates of the press using gesture.location(in:)
Ref: https://developer.apple.com/documentation/uikit/uigesturerecognizer/1624219-location
Then use indexPathForItem(at:)
to retrieve the IndexPath of the cell touched. Ref: https://developer.apple.com/documentation/uikit/uicollectionview/1618030-indexpathforitem
Based on this you probably do not need a different gesture recognizer for each cell, you can probably register it with the collection view once.
Solution provided by George Heints based on the above:
@objc func longPress(_ longPressGestureRecognizer: UILongPressGestureRecognizer) {
if longPressGestureRecognizer.state == UIGestureRecognizer.State.began {
let touchPoint = longPressGestureRecognizer.location(in: collectionView)
if let index = collectionView.indexPathForItem(at: touchPoint) {
self.delegateAlbumView?.longPressGetstureDetected(id: albumsDataOrigin[index.row].id ?? 0)
}
}
}
I would recommend to use the State.recognized instead of State.began, your mileage may vary!
How to get cell atIndex in UICollectionView with swift?
This is the way to get the cell at a given indexPath:
let cell = collectionView!.cellForItemAtIndexPath(indexPath)
However, you also might want to try:
cell.contentView.backgroundColor = UIColor.blueColor()
NOTE:
Though the above may have worked, I want to encourage you to try a different implementation to achieve the same functionality. Your implementation would require you to have a separate Action# function for each CollectionViewCell, as well as create the indexPath manually in each of those methods, when you could potentially only have one!
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as! CollectionViewCell
cell.backgroundColor = UIColor.blackColor()
cell.buttonView.addTarget(self, action: Selector("action"), forControlEvents: UIControlEvents.TouchUpInside)
return cell
}
and the function for that one method would be something like:
func action(sender: UIButton!) {
var point : CGPoint = sender.convertPoint(CGPointZero, toView:collectionView)
var indexPath = collectionView!.indexPathForItemAtPoint(point)
let cell = collectionView!.cellForItemAtIndexPath(indexPath)
cell.backgroundColor = UIColor.blueColor()
}
Updated action function for Swift 4.2
@objc func action(sender: Any){
print("tickedOffPressed !")
if let button = sender as? UIButton {
let point: CGPoint = button.convert(.zero, to: collectionView)
if let indexPath = collectionView!.indexPathForItem(at: point) {
let cell = collectionView!.cellForItem(at: indexPath)
cell?.backgroundColor = UIColor.blue
}
}
}
Just a suggestion! Happy coding! :)
Cannot get indexPath and selection on Collection View
Seems like your problem relates to the UITapGestureRecognizer
you are adding to your view in configureSuperView()
. The touches that would usually trigger the collectionView didSelectItemAt...
delegate function are being sent to the gesture recognizer's handler, which is hideKeyboard()
.
Comment the line with view.addGestureRecognizer(viewTap)
and your code will work. If so, I can also help you with achieving the hideKeyboard
functionality, just let me know.
How to get CollectionViewCell indexPath on Out-sided UIButton Click
import UIKit
class ViewController: UIViewController ,UICollectionViewDelegate&UICollectionViewDataSource&UICollectionViewDelegateFlowLayout{
@IBOutlet weak var collectionView: UICollectionView!
var currentIndexPath:IndexPath!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
collectionView.delegate = self
collectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
cell.backgroundColor = indexPath.row % 2 == 1 ? .blue : .red
return cell
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
currentIndexPath = indexPath
}
@IBAction func indexPathAction(_ sender: UIButton) {
print("Current IndexPath",currentIndexPath)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return collectionView.bounds.size
}
}
Selector In Swift 3.0
You can declare selector in Swift 3 like this.
var itemSelected: Selector?
Or
var itemSelected = #selector(tapGesture)
Later you can use above itemSelected
selector with action like this.
For eg:
let tap = UITapGestureRecognizer(target: self, action: itemSelected)
And tapGesture
is declared like
func tapGesture(_ sender: UITapGestureRecognizer) { }
Edit: You have added collectionView
inside your TableViewCell
, so to get the selected IndexPath of CollectionViewCell
, declare one protocol and use it with your tableViewCell.
protocol SelectedCellDelegate {
func getIndexPathOfSelectedCell(tableIndexPath: IndexPath, collectionViewCell indexPath: IndexPath)
}
Now create one instance of SelectedCellDelegate and instance of IndexPath
within your CustomTableViewCell.
class CustomTableCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource {
//All outlet
var delegate: SelectedCellDelegate?
var tableCellIndexPath = IndexPath()
//CollectionViewDataSource method
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.delegate?.getIndexPathOfSelectedCell(tableIndexPath: tableCellIndexPath, indexPath: indexPath)
}
}
Now inside your ViewController where you have added TableView implement the protocol SelectedCellDelegate
and set the delegate
and tableCellIndexPath
in cellForRowAt indexPath
method.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, SelectedCellDelegate {
//your methods
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell // Initialize the cell with your custom TableCell
cell.delegate = self
cell.tableCellIndexPath = indexPath
return cell
}
Now add the delegate method in your ViewController.
func getIndexPathOfSelectedCell(tableIndexPath: IndexPath, collectionViewCell indexPath: IndexPath) {
print("TableView cell indexPath - \(tableIndexPath)")
print("CollectionView cell indexPath - \(indexPath)")
}
Related Topics
Retain Cycle (Strong Reference) Fix for Custom Uitextfield
CSS Styled Scrollbars Support for Safari Mobile on iOS 6 Disappeared
Implementing Fast and Efficient Core Data Import on iOS 5
Paging Uiscrollview in Increments Smaller Than Frame Size
How to Change the Color of the Text in a Uipickerview Under iOS 7
How to Implement Two Inits with Same Content Without Code Duplication in Swift
Difference Between Presentviewcontroller and Uinavigationcontroller
Getting Username and Profile Picture from Facebook iOS 7
Uitextview Cursor Below Frame When Changing Frame
Firebase Fcm Silent Push Notifications for iOS
Getter VS Computed Property. What Would Warrant Using One of These Approaches Over the Other
Why Does CSS Background-Size: Cover Not Work in Portrait Mode on iOS
Xcode 8/Swift 3: "Expression of Type Uiviewcontroller? Is Unused" Warning
How to Dismiss Keyboard iOS Programmatically When Pressing Return
Detect If App Is Running in Slide Over or Split View Mode in iOS 9