Adding UITapGestureRecognizer to subview on tableViewCell - ios

everyone, I am trying to add gesture recognizer to StackView which located on TableViewCell with that code and it doesn't work:
#IBOutlet var categoryStackView: UIStackView! {
didSet {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(categoryStackViewTapped))
categoryStackView.addGestureRecognizer(tapGesture)
}
}
And it doesn't work, I checked StackView and it is enable for user interactive
#objc func categoryStackViewTapped(sender: UITapGestureRecognizer) {
print("Here we are")
}

I am suggesting another approach if you have multiple stackView in your tableView. Add the current index row as tag to your , and then add click action to your button handler function.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! Cell
cell.stackView.tag = indexPath.row
cell.stackView.addTarget(self, action:#selector(categoryStackViewTapped(sender:)), for: .touchUpInside)
return cell
}
Then in your handler function, you can get the correct index path by reading this tag
func categoryStackViewTapped(sender: UIStackView) {
let myIndexPath = IndexPath(row: sender.tag, section: 0)
//... other code here
}

Related

iOS swift: UICollectionview horizontal scroll single cell not reloading

In my application UICollection scroll horizontally. collection-view cell two button and one UIView was designed.
Each cell loaded two button. when user click one button the particular cell should be reload and the UIView will be displayed in that cell only other cell not displayed.
Here i attached the collectionview image:
Here my code:
#IBOutlet weak var dataCollectionView: UICollectionView!
var addIndexArray:[Int] = []
var arraySelectedFilterIndex = [IndexPath]()
self.listArr = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t"]
override func viewDidLoad() {
super.viewDidLoad()
self.dataCollectionView.reloadData()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return (lvsnListArr.count/2)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = dataCollectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier_CollectionView, for: indexPath as IndexPath) as! DataCell
if self.arraySelectedFilterIndex.contains(indexPath) {
cell.buttonView.isHidden = false
}else{
cell.buttonView.isHidden = true
}
cell.btn1.setTitle(lvsnListArr[2 * indexPath.row], for: .normal)
cell.btn1.tag = indexPath.row
cell.btn1.addTarget(self, action: #selector(btnPressed(sender:)), for: .touchUpInside)
cell.btn2.setTitle(lvsnListArr[2 * indexPath.row + 1], for: .normal)
cell.btn2.tag = indexPath.row
cell.btn2.addTarget(self, action: #selector(btn2Pressed(sender:)), for: .touchUpInside)
return cell
}
#objc func btnPressed(sender: UIButton) {
self.addIndexArray.append(sender.tag)
let hitPoint = sender.convert(CGPoint.zero, to: dataCollectionView)
if let indexPath = dataCollectionView.indexPathForItem(at: hitPoint) {
print("indexPath--->",indexPath)
self.arraySelectedFilterIndex.append(getIndexPath)
self.dataCollectionView.reloadItems(at: [getIndexPath])
}
}
#objc func btn2Pressed(sender: UIButton) {
self.addIndexArray.append(sender.tag)
let hitPoint = sender.convert(CGPoint.zero, to: dataCollectionView)
if let indexPath = dataCollectionView.indexPathForItem(at: hitPoint) {
print("indexPath--->",indexPath)
self.arraySelectedFilterIndex.append(getIndexPath)
self.dataCollectionView.reloadItems(at: [getIndexPath])
}
}
My error:
I clicked cell btn1 one action btnPressed single cell over load and display the next cell image both images are overlap in collectionview.
Here i attached my issue cell image.
Here i got cell indexpath and indexpath.row, how can i validate and fix this issue in cell for row. struggling this point.
Kinldy help to fix this issues. Thanks advance.
You can reload single cell like you are doing in button action
self.dataCollectionView.reloadItems(at: [getIndexPath])
OR
You can get cell in button action like as below
if let cell = self.dataCollectionView.cellForItem(at: indexPath) as? DataCell
{
//Here you can write your view hide show code
if self.arraySelectedFilterIndex.contains(indexPath)
{
cell.buttonView.isHidden = false
}
else
{
cell.buttonView.isHidden = true
}
}

How to get the get a index.row and index section from a UITableViewCell with an UIStepper programmatically using Swift 4 [duplicate]

I have table view cells like quiz. And in each cell I have a buttons And how can I identify in which cell button was pressed. Maybe by IndexPath???
This is how I connected button to
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "QuestionCell")!
variant1 = cell.contentView.viewWithTag(1) as! UIButton
variant2 = cell.contentView.viewWithTag(2) as! UIButton
variant3 = cell.contentView.viewWithTag(3) as! UIButton
variant4 = cell.contentView.viewWithTag(4) as! UIButton
variant1.addTarget(self, action: #selector(self.variant1ButtonPressed), for: .touchUpInside)
variant2.addTarget(self, action: #selector(self.variant2ButtonPressed), for: .touchUpInside)
variant3.addTarget(self, action: #selector(self.variant3ButtonPressed), for: .touchUpInside)
variant4.addTarget(self, action: #selector(self.variant4ButtonPressed), for: .touchUpInside)
return cell
}
func variant1ButtonPressed() {
print("Variant1")
variant1.backgroundColor = UIColor.green
}
func variant2ButtonPressed() {
print("Variant2")
variant2.backgroundColor = UIColor.green
}
func variant3ButtonPressed() {
print("Variant3")
variant3.backgroundColor = UIColor.green
}
func variant4ButtonPressed() {
print("Variant4")
variant4.backgroundColor = UIColor.green
}
This is how it looks like in Storyboard:
You should use delegate pattern, basic example:
protocol MyCellDelegate {
func didTapButtonInside(cell: MyCell)
}
class MyCell: UITableViewCell {
weak var delegate: MyCellDelegate?
func buttonTapAction() {
delegate?.didTapButtonInside(cell: self)
}
}
class ViewController: MyCellDelegate {
let tableView: UITableView
func didTapButtonInside(cell: MyCell) {
if let indexPath = tableView.indexPath(for: cell) {
print("User did tap cell with index: \(indexPath.row)")
}
}
}
Use this line to get indexPath, Where you have to pass UIButton on target selector
func buttonTapped(_ sender:AnyObject) {
let buttonPosition:CGPoint = sender.convert(CGPointZero, to:self.tableView)
let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
}
Since actions need to be inside the view controller, ctrl + drag from your button to the view controller - this will use the responder chain.
Basically you need to convert the view (button) to the coordinate system of the table view in order to tell what is the IndexPath and if you have the IndexPath you have the object that corresponds to the button inside the cell that was tapped:
#IBAction func buttonTapped(_ sender: Any) {
if let indexPath = indexPath(of: sender) {
// Your implementation...
}
}
private func indexPath(of element:Any) -> IndexPath? {
if let view = element as? UIView {
// Converting to table view coordinate system
let pos = view.convert(CGPoint.zero, to: self.tableView)
// Getting the index path according to the converted position
return tableView.indexPathForRow(at: pos) as? IndexPath
}
return nil
}
It is important to mention that there many solutions for your question. But you should know that in Apple's sample projects they also use this technic.
This is how you add tag to a UIButton inside UITableView, add below lines of code in
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
cell.yourButton.tag = indexPath.row
cell.yourButton.addTarget(self, action:#selector(btnPressed(sender:)), for: .touchUpInside)
Add this function in your ViewController
func btnPressed(sender: UIButton)
{
print("Button tag \(sender.tag)")
}
Hope this helps...
Simple Subclass button just like JSIndexButton
class JSIndexButton : UIButton {
var indexPath : IndexPath!
}
Now at cellForRowAt
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ItemCell
let itemCategory = dataList[button.indexPath.section];
let item = itemCategory.items[button.indexPath.row];
cell.imgView.setImageWithURL(item.photoUrl);
cell.btnBuy.indexPath = indexPath;
cell.btnBuy.addTarget(self, action: #selector(JSCollapsableTableView.btnBuyPressed(_:)), for: UIControlEvents.touchUpInside)
return cell;
}
Check Button Action
#IBAction func btnBuyPressed(_ button: JSIndexButton) {
let itemCategory = dataList[button.indexPath.section];
let item = itemCategory.items[button.indexPath.row];
}
#objc func ItemsDescription(_ sender: UIButton?,event: AnyObject?) {
let touches: Set<UITouch>
touches = (event?.allTouches!)!
let touch:UITouch = (touches.first)!
let touchPosition:CGPoint = touch.location(in: self.tableView)
let indexPath:NSIndexPath = self.tableView.indexPathForRow(at: touchPosition)! as NSIndexPath
}
adding target
cell.ItemsDescription.addTarget(self, action: #selector(ItemsDescription(_:event:)), for: UIControlEvents.touchUpInside)

Swift Change label text color on tap from within TableViewCell

I have a UILabel that is inside a TableView, I want to change the color of the UILabel to red on user tap. I am using a UITapGestureRecognizer and on tapping the UILabel I can get the content of the UILabel but I can't get the actual UILabel since to my knowledge you can't have parameters inside a UIGesture function.
This is my code and it will help clear things up
class HomeProfilePlacesCell: NSObject {
var Post = [String]()
#objc func PostTap(_ sender: UIGestureRecognizer) {
print(Post[(sender.view?.tag)!])
}
func HomeProfilePlaceTVC(_ tableView: UITableView, cellForRowAt indexPath: IndexPath, streamsModel : streamModel,HOMEPROFILE: HomeProfile, controller: UIViewController) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeTVC", for: indexPath) as! HomeTVC
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(PostTap(_:)))
tapGesture.delegate = self as? UIGestureRecognizerDelegate
cell.post.addGestureRecognizer(tapGesture)
cell.post.text = streamsModel.Posts[indexPath.row]
cell.post.tag = indexPath.row
Post = streamsModel.Posts
return cell
}
}
My function there is PostTap whenever a user taps the UILabel which is the cell.post then I can read it's content inside PostTap but in order to change the color of that UILabel then I'll have to pass the let cell constant into the PostTap function.
Is there anyway I can do that or a work around ? I am new to Swift
Use TableView Delegates: [SWIFT 4.0]
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let cell = tableView.cellForRowAtIndexPath(indexPath) as! <your Custom Cell>
cell.<your CustomCell label name>.textColor = UIColor.red
//OR
cell.<your Customcell label name>.backgroundColor = UIColor.green
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
}
func tableView(tableView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath)
{
let cell = tableView.cellForRowAtIndexPath(indexPath) as! <your Custom Cell>
// change color back to whatever it was
cell.<your Customcell label name>.textColor = UIColor.black
//OR
cell.<your Customcell label name>.backgroundColor = UIColor.white
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
}
Add tag to cell as indexPath.row
cell.tag = indexPath.row
Then
#objc func PostTap(_ sender: UIGestureRecognizer) {
let cell = self.tableVIew.cellForRow(at: sender.tag) as! HomeTVC
// Now you access your cell label here, and can do whatever you want
}
you can make it possible by using
tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath)
when user tap on a cell this method called
in this method do this
tableView.cellForRow(at: indexPath)
this will give you cell cast it as your cell class
and now u can do anything with your label in that cell
cell.label....
To change the color of clicked index label first you need to declare on varible to identify the clicked position
var selectedCellIndex = "" // initialize as empty string
In you cellForRowAt
func HomeProfilePlaceTVC(_ tableView: UITableView, cellForRowAt indexPath: IndexPath, streamsModel : streamModel,HOMEPROFILE: HomeProfile, controller: UIViewController) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeTVC", for: indexPath) as! HomeTVC
cell.post.text = streamsModel.Posts[indexPath.row]
cell.post.tag = indexPath.row
cell.post.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(PostTap(_:)))
tapGesture.delegate = self as? UIGestureRecognizerDelegate
cell.post.addGestureRecognizer(tapGesture)
Post = streamsModel.Posts
if self.selectedCellIndex == "\(indexPath.row)" {
cell.post.text = UIColor.red
} else {
cell.post.text = UIColor.blue
}
return cell
}
In your Tap function
func PostTap(_ sender:UIGestureRecognizer){
let tapView = gesture.view!
let index = tapView.tag
self. selectedCellIndex = "\(index)"
self.YOUR_TABLE_NAME.reloadData()
}
Hope this will help you
Try Closure approach in Cell:
In Custom Table View cell:
class HomeTVC: UITableViewCell {
#IBOutlet weak var labelPost: UILabel!
var callBackOnLabelTap: (()->())?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(postTap(_:)))
tapGesture.numberOfTapsRequired = 1
tapGesture.delegate = self
self.labelPost.addGestureRecognizer(tapGesture)
}
#objc func postTap(_ sender: UIGestureRecognizer) {
self.callBackOnLabelTap?()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Then in cellForRowAt indexPath :
func HomeProfilePlaceTVC(_ tableView: UITableView, cellForRowAt indexPath: IndexPath, streamsModel : streamModel,HOMEPROFILE: HomeProfile, controller: UIViewController) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeTVC", for: indexPath) as! HomeTVC
cell.callBackOnLabelTap = {
cell.labelPost.backgroundColor = UIColor.black
}
return cell
}
For me, I wanted the color for the label to change when the container cell of a label is tapped.
You can select what color you want for the Label text, when tapped by selecting, Highlighted (in Attributes inspector) for Label. From drop down you can select the color you want to see when the cell was tapped.
Attributes Inspector: Highlighted Property for label

Selected button of a UITableViewCell get disappear when scrolling

I'm working on a project coded in swift 3 and I have a UIButton inside a UITableViewCell where the image changes once the button is tapped. Though the selected buttons get selected as intended, once the UITableview scrolls the selected images gets disappear since the cells are been reused. As I'm new to programming having troubles of writing the logic. Help would much appreciate the code as bellow.
CellFoRow
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
//Button_Action
addSongButtonIdentifier(cell: cell, indexPath.row)
}
This is where the cell is been created.
func addSongButtonIdentifier(cell: UITableViewCell, _ index: Int) {
let addButton = cell.viewWithTag(TABLE_CELL_TAGS.addButton) as! UIButton
//accessibilityIdentifier is used to identify a particular element which takes an input parameter of a string
//assigning the indexpath button
addButton.accessibilityIdentifier = String (index)
// print("visible Index:",index)
print("Index when scrolling :",addButton.accessibilityIdentifier!)
addButton.setImage(UIImage(named: "correct"), for: UIControlState.selected)
addButton.setImage(UIImage(named: "add_btn"), for: UIControlState.normal)
addButton.isSelected = false
addButton.addTarget(self, action: #selector(AddToPlaylistViewController.tapFunction), for:.touchUpInside)
}
the tap function
func tapFunction(sender: UIButton) {
print("IndexOfRow :",sender.accessibilityIdentifier!)
// if let seporated by a comma defines, if let inside a if let. So if the first fails it wont come to second if let
if let rowIndexString = sender.accessibilityIdentifier, let rowIndex = Int(rowIndexString) {
self.sateOfNewSongArray[rowIndex] = !self.sateOfNewSongArray[rowIndex]//toggle the state when tapped multiple times
}
sender.isSelected = !sender.isSelected //image toggle
print(" Array Data: ", self.sateOfNewSongArray)
selectedSongList.removeAll()
for (index, element) in self.sateOfNewSongArray.enumerated() {
if element{
print("true:", index)
selectedSongList.append(songDetailsArray[index])
print("selectedSongList :",selectedSongList)
}
}
}
You need to maintain the button selection status at the controller level. You need to make changes to the model that you are using to configure your tableview.
I have created a similar scenario. I have used an array selectionStatusArray to maintain the button's selection status.
Example:
1. UIViewController containing UITableView
class ViewController: UIViewController, UITableViewDataSource
{
#IBOutlet weak var tableView: UITableView!
var selectionStatusArray = [false, false, false, false, false] //Array that maintains the button selection status
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return selectionStatusArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TableViewCell
addSongButtonIdentifier(cell: cell, indexPath.row)
return cell
}
func addSongButtonIdentifier(cell: TableViewCell, _ index: Int)
{
cell.addButton.tag = index
cell.addButton.isSelected = selectionStatusArray[index]
cell.tapHandler = {
self.selectionStatusArray[$0] = cell.addButton.isSelected
}
}
}
2. Custom UITableViewCell
class TableViewCell: UITableViewCell
{
#IBOutlet weak var addButton: UIButton!
var tapHandler: ((Int)->())?
#IBAction func tapFunction(_ sender: UIButton)
{
sender.isSelected = !sender.isSelected
tapHandler?(sender.tag)
}
}
You can configure the UITableViewCell according to your requirements.
You have this code addButton.isSelected = false which is causing the problem because I believe you are calling the function addSongButtonIdentifier inside tableView delegate method, you should not set all those property inside tableView delegate.
Instead you should do it initially and only once for each of your cell like either in storyboard itself or by providing a model to cell class.

Adding a gesture recognizer to an image view in a table cell

How can I add a Gesture Recognizer to a UIImageView in a table cell? I want it so that if a user taps an image in the cell, the image will change and the data model will update.
I know this needs to be set up in the UITableViewController. My code currently can execute a command if anywhere in the cell is tapped, but I would like it to execute only if the image is tapped, not anywhere in the cell.
I setup up the gesture recognizer in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
// Load sample data
loadSampleHabits()
// Initialize tap gesture recognizer
var recognizer = UITapGestureRecognizer(target: self, action: #selector(tapEdit(recognizer:)))
// Add gesture recognizer to the view
self.tableView.addGestureRecognizer(recognizer)
And this is the function
//action method for gesture recognizer
func tapEdit(recognizer: UITapGestureRecognizer) {
if recognizer.state == UIGestureRecognizerState.ended {
let tapLocation = recognizer.location(in: self.tableView)
if let tapIndexPath = self.tableView.indexPathForRow(at: tapLocation) {
if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) as? HabitTableViewCell {
print("Row Selected")
}
}
}
As a secondary question, are there any conflicts if I want to add a gesture recognizer to the cell and the image view within the cell?
You are adding gesture recognizer on your tableview instead of imageView as you required. Yo need to move your code from viewDidLoad to cellForRowAtIndexPath and add gesture to imageView in each cell while configuing your cell.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
var recognizer = UITapGestureRecognizer(target: self, action: #selector(tapEdit(recognizer:)))
// Add gesture recognizer to your image view
cell.yourimageview.addGestureRecognizer(recognizer)
}
Note: Do make sure to enable userinteraction of your image view
cell.yourimageview.userInteractionEnabled = YES;
For your requirement I will suggest using UILongPressGestureRecognizer as it has less chances of conflict in gesture and didselect. Yo can add UILongPressGestureRecognizer in viewDidLoad and access it as per your requirement.
let lpgr = UILongPressGestureRecognizer(target: self, action: #selector(ViewController.handleLongPress(_:)))
lpgr.minimumPressDuration = 1
tableView.addGestureRecognizer(lpgr)
Define method as
func handleLongPress(_ gesture: UILongPressGestureRecognizer){
if gesture.state != .began { return }
let tapLocation = gesture.location(in: self.tableView)
if let tapIndexPath = self.tableView.indexPathForRow(at: tapLocation) {
if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) as? HabitTableViewCell {
print("Row Selected")
}
}
You can try removing if recognizer.state == UIGestureRecognizerState.ended condition from your method.
UITapGestureRecognizer is a discrete gesture, and as such, your event handler is called only once when the gesture was recognized. You don't have to check the state at all. Certainly you won't receive a call for the state of .Began. For more info consider #Rob ans here.
Add This line in cell for row at index path
var recognizer = UITapGestureRecognizer(target: self, action: #selector(tapEdit(recognizer:)))
// Add gesture recognizer to the view
cell.yourimageviewname.addGestureRecognizer(recognizer)
cell.yourimageviewname.userInteractionEnabled = true;
For my suggestion you have to use UIButton in cell, for performance
improvements,
UIButtons
Specially designed for this and have been extensively optimized by Apple for touches.
If you want image in cell you can use UIButton with Image inside.
I have had design a solution like this. I just write a sample code below:
import UIKit
protocol CellImageTapDelegate {
func tableCell(didClickedImageOf tableCell: UITableViewCell)
}
class SampleCell : UITableViewCell {
var delegate : CellImageTapDelegate?
var tapGestureRecognizer = UITapGestureRecognizer()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialize()
}
private func initialize() {
tapGestureRecognizer.addTarget(self, action: #selector(SampleCell.imageTapped(gestureRecgonizer:)))
self.addGestureRecognizer(tapGestureRecognizer)
}
func imageTapped(gestureRecgonizer: UITapGestureRecognizer) {
delegate?.tableCell(didClickedImageOf: self)
}
}
class ViewController: UITableViewController, CellImageTapDelegate {
// CellImageTapDelegate
func tableCell(didClickedImageOf tableCell: UITableViewCell) {
if let rowIndexPath = tableView.indexPath(for: tableCell) {
print("Row Selected of indexPath: \(rowIndexPath)")
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SampleCellID", for: indexPath) as! SampleCell
cell.delegate = self
return cell
}
}
remember to do following in storyboard
1. enable user interaction of imageview
2. set class of tableviewcell
3. set reuse identifier of tableviewcell
// create an instance of UITapGestureRecognizer and tell it to run
// an action we'll call "handleTap:"
let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
// we use our delegate
tap.delegate = self
// allow for user interaction
cell.imageViewName.userInteractionEnabled = true
// add tap as a gestureRecognizer to tapView
cell.imageViewName.addGestureRecognizer(tap)
import UIKit
class UserInfoCell: UITableViewCell{
#IBOutlet weak var imagePlaceholder: UIImageView!
}
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UIImagePickerControllerDelegate,UINavigationControllerDelegate {
#IBOutlet weak var tableView: UITableView!
let imagePicker = UIImagePickerController()
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "UserInfoCell" ,for: indexPath ) as! UserInfoCell
let recognizer = UITapGestureRecognizer(target: self, action: #selector(self.openGallery))
cell.imagePlaceholder.addGestureRecognizer(recognizer)
recognizer.numberOfTapsRequired = 1
cell.imagePlaceholder.isUserInteractionEnabled = true
cell.name.text = "Akshay"
if let data = UserDefaults.standard.data(forKey: "savedImage") {
cell.imagePlaceholder.image = UIImage(data: data as Data)
}
return cell
}
#objc func openGallery(){
imagePicker.sourceType = .photoLibrary
present(imagePicker,animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let userimage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
let imageData = userimage.jpegData(compressionQuality: 1)!
UserDefaults.standard.setValue(imageData, forKey: "savedImage")
print("image found")
self.imagePicker.dismiss(animated: true, completion: nil)
self.tableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
imagePicker.delegate = self
tableView.tableFooterView = UIView()
}
}
This code select image from gallery using Tapgesture of ImageView inside a TableViewCell

Resources