Button inside the CollectionView repeating the first cell information - ios

i am creating images app from my Wordpress website's json using swift , i have created CollectionView and every cell displaying images and working fine but i want to add show comment in every cell for each post, its showing the exact comments for every post/cell but when i click on it it shows the comments of very first post of collection view. this is my code to show comments and for clickable button.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! homeViewCell
let url = dataArray[indexPath.row]["thumbnail_images"]["medium"]["url"].stringValue
cell.imageArticle.sd_setImage(with: NSURL(string: url) as URL?, placeholderImage:UIImage(named: "empty.png"))
cell.nametag.text = String(htmlEncodedString:dataArray[indexPath.row]["tags"][0]["title"].stringValue)
cell.nametagg.text = String(htmlEncodedString:dataArray[indexPath.row]["categories"][0]["title"].stringValue)
cell.fbButton.addTarget(self, action: #selector(homeController.fbClick), for: .touchUpInside)
cell.commentButton.addTarget(self, action: #selector(homeController.comment), for: .touchUpInside)
cell.commentButton.setTitle("\(dataArray[indexPath.row]["comment_count"].stringValue) comments", for: .normal)
cell.leaveComment.addTarget(self, action: #selector(homeController.leavecomment), for: .touchUpInside)
cell.contentline.text = String(htmlEncodedString:dataArray[indexPath.row]["excerpt"].stringValue)
return cell
}
and this is the code for button click
#objc func comment(_ sender: Any) {
let vc = CommentViewController()
vc.dataArray = dataArray[indexPath.row]["comments"].array
self.navigationController!.pushViewController(vc, animated: true)
}
i hope you understand my question, thanks

You've declared the indexPath as a global variable and it's value is NSIndexPath(row: 0, section: 0) as you said.
in comments(_:) function you've used indexPath.row but this row is 0 so it is first post's comments.
You don't need to set tapgesture to cell's button.
In homeViewCell you should create IBAction for the button and call closure when it triggered ->
class homeViewCell: UICollectionViewCell {
public var didTapComment: (() -> Void)?
#IBAction func didTapCommentButton(_ sender: UIButton) {
didTapComment?()
}
}
Set didTapComment's action in cellForItemAt like this ->
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! homeViewCell
cell.didTapComment = { [weak self] in
let vc = CommentViewController()
vc.dataArray = dataArray[indexPath.row]["comments"].array
self?.navigationController!.pushViewController(vc, animated: true)
}
let url = dataArray[indexPath.row]["thumbnail_images"]["medium"]["url"].stringValue
cell.imageArticle.sd_setImage(with: NSURL(string: url) as URL?, placeholderImage:UIImage(named: "empty.png"))
cell.nametag.text = String(htmlEncodedString:dataArray[indexPath.row]["tags"][0]["title"].stringValue)
cell.nametagg.text = String(htmlEncodedString:dataArray[indexPath.row]["categories"][0]["title"].stringValue)
cell.fbButton.addTarget(self, action: #selector(homeController.fbClick), for: .touchUpInside)
cell.commentButton.setTitle("\(dataArray[indexPath.row]["comment_count"].stringValue) comments", for: .normal)
cell.leaveComment.addTarget(self, action: #selector(homeController.leavecomment), for: .touchUpInside)
cell.contentline.text = String(htmlEncodedString:dataArray[indexPath.row]["excerpt"].stringValue)
return cell
}
}
Remove followings;
cell.commentButton.addTarget(self, action: #selector(homeController.comment), for: .touchUpInside) line from cellForItemAt
#objc func comment(_ sender: Any) function
let indexPath = NSIndexPath(row: 0, section: 0)

Related

UISwitch is not invoking the function when added with tableView cell

I have added a switch along with each cell in table view but the switch function is not get called. If I give the switch in the front page its displaying successfully. But in tableview cell its not working `
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = models[indexPath.row].Address
cell.textLabel?.text = models[indexPath.row].Number
cell.textLabel?.text = models[indexPath.row].Role
cell.textLabel?.text = models[indexPath.row].Name
//switch
let mySwitch = UISwitch(frame: .zero)
mySwitch.setOn(false, animated: true)
mySwitch.tag = indexPath.row
mySwitch.tintColor = UIColor.red
mySwitch.onTintColor = UIColor.green
mySwitch.addTarget(self, action: #selector(switchValueDidChange(_:)), for: .valueChanged)
cell.accessoryView = mySwitch
return cell
}
#IBAction func switchValueDidChange(_sender: UISwitch){
if _sender .isOn{
print("switch on")
view.backgroundColor = UIColor.red }
else{
view.backgroundColor = UIColor.systemPurple
}
}
`
The signature is wrong. There must be a space character between the underscore and sender. And if it's not a real IBAction replace #IBAction with #objc
#objc func switchValueDidChange(_ sender: UISwitch) {
if sender.isOn {...
and – not related to the issue – the selector can be simply written
#selector(switchValueDidChange)

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
}
}

UIButton interaction is not smooth when used in UICollectionViewCell

I Have a UICollectionViewCell in which I have added UIButton. Normally button action gets called but some times it does not. When same button I add in a viewcontroller the interaction is very smooth. Even a gentle tap trigger the action.
Below is the code for button :
func makeTapButton(for superView: UIView) -> UIButton {
let offSetValue = 15
let button = UIButton()
button.backgroundColor = UIColor.yellow
superView.addSubview(button)
button.snp.makeConstraints { (make) in
make.leading.equalToSuperview().offset(-offSetValue)
make.trailing.equalToSuperview().offset(offSetValue)
make.top.equalToSuperview().offset(-offSetValue)
make.bottom.equalToSuperview().offset(offSetValue)
}
return button
}
func setupCustomView() {
self.addSubview(containerStackView)
containerStackView.snp.makeConstraints { (make) -> Void in
make.top.equalTo(self)
make.leading.equalTo(self)
make.trailing.equalTo(self)
make.bottom.equalTo(self)
}
containerStackView.addArrangedSubview(commentStack)
containerStackView.addArrangedSubview(retweetStack)
containerStackView.addArrangedSubview(likeStack)
commentStack.addArrangedSubview(commentImageView)
commentStack.addArrangedSubview(commentsCountLabel)
retweetStack.addArrangedSubview(retweetImageView)
retweetStack.addArrangedSubview(retweetCountLabel)
likeStack.addArrangedSubview(likeImageView)
likeStack.addArrangedSubview(likesCountLabel)
likeButton = makeTapButton(for: likeStack)
commentButton = makeTapButton(for: commentStack)
retweetButton = makeTapButton(for: retweetStack)
}
try below mentioned code when using UIbutton placed in collectionview
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath) as! UICollectionViewCell
cell.btnName.addTarget(self, action: #selector(btnSelClk), for: .touchUpInside)
cell.binSel.tag = collectionView.tag
cell.binSel.accessibilityValue = String(indexPath.row)
return cell
}
#objc func btnSelClk(sender:UIButton) {
selectAry[sender.tag] = sender.accessibilityValue!
// your button action
}
Defining your buttons in UICollectionViewCell class and your functions in UIViewController class being less laggy because they are reused;
import UIKit
class YourCell: UITableViewCell {
#IBOutlet weak var yourBtn: UIButton!
var yourButtonAction: (() -> ())?
#IBAction func buttonPressed(_ sender: UISlider) {
yourButtonAction()
}
}
then in your ViewController where you call your cell;
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCell", for: indexPath) as! YourCell
cell.yourBtn = {[unowned self] in
// call your functions here, I hope this will be less laggy
print("button pressed")
}
}

Perform segue depending on image tapped in TableViews custom cell

Simple as my question on title. I'm trying to go to another view controller depending on the image that someone tap on my table view. Eg: If you tapped on image1 perform segue gotoview1, if you tapped on image2 perform segue gotoview2.
I have an array of the images:
let gameImages = [UIImage(named: "DonkeyKong"), UIImage(named: "TRex"), UIImage(named: "SuperMarioRun"), UIImage(named: "Arcades1")]
and this is my cell for index, I tried to perfom the segue with the func imageAction but the app will crash:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
cell.frontImage.image = gameImages[indexPath.row]
cell.title.text = gameTitles[indexPath.row]
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "imageAction:")
cell.frontImage.isUserInteractionEnabled = true
cell.frontImage.addGestureRecognizer(tapGestureRecognizer)
func imageAction(_ sender:AnyObject) {
if cell.frontImage.image == UIImage(named: "DonkeyKong"){
performSegue(withIdentifier: "goToDonkey", sender: self)
}
}
return cell
}
I have a custom cell where I just linked the images as an outlet and perform some basic modifications. Just saying in case this matters.
try this instead.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
cell.imageButton.addTarget(self, action: #selector(self.imageAction(_:)), for: .touchUpInside)
cell.imageButton.tag = indexPath.row
cell.frontImage.image = gameImages[indexPath.row]
cell.title.text = gameTitles[indexPath.row]
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "imageAction:")
cell.frontImage.isUserInteractionEnabled = true
cell.frontImage.addGestureRecognizer(tapGestureRecognizer)
return cell
}
func imageAction(_ sender:UIButton) {
switch sender.tag{
case 0:
self.performSegue(withIdentifier: "goToDonkey", sender: self)
case 1:
performSegue(withIdentifier: "goToTRex", sender: self)
case 2:
performSegue(withIdentifier: "goToSuperMarioRun", sender: self)
case 3:
performSegue(withIdentifier: "goToArcades1", sender: self)
default:
break
}
}
imageAction function is not member of self since is part o a tableview delegate function not self. that's why the unrecognized selector instance.
but i maybe rewrite the func using another delegate, but since you dnt want to use the cell didselect only the image this may solve your problem.

Selector to get indexPath UICollectionView Swift 3.0

I'm trying to get indexPath on the cell when it is tapped twice.
I'm passing arguments in Selector like this but it is giving error.
What is the correct format for this ?
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let subOptioncell : SubOptionsCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: subOptionsCVReuseIdentifier, for: indexPath) as! SubOptionsCollectionViewCell
let imageNamed = "\(customizeOptionSelected[indexPath.row])"
subOptioncell.subOptionsImage.image = UIImage(named: imageNamed)
let tap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped(sender: indexPath)))
tap.numberOfTapsRequired = 2
collectionView.addGestureRecognizer(tap)
return subOptioncell
}
}
func doubleTapped(sender: IndexPath) {
print("Double Tap")
}
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
}
}
}
The correct selector in your case is doubleTapped:. That is
let tap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped:))
You can not fire arbitrary parameter when the target method is called. You can set target on subOptioncell by
let tap = UITapGestureRecognizer(target: subOptioncell, action: #selector(doubleTapped:))
And you can set whatever arbitrary object.parameter you want in subOptioncell
You need to add Selector like this way
let tap = UITapGestureRecognizer(target: self, action: #selector(YourViewControllerName.doubleTapped(_:)))
subOptioncell.addGestureRecognizer(tap)
Change your code to.
let tap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped(_:)))
and the function to.
func doubleTapped(_ sender: AnyObject) {
print("Double Tap")
}
At your Datasource method
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let subOptioncell : SubOptionsCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: subOptionsCVReuseIdentifier, for: indexPath) as! SubOptionsCollectionViewCell{
//... your code
subOptioncell.addGestureRecognizer(tap)
return subOptioncell
}
}
Then at the function cellTapped()
func cellTapped(sender: UITapGestureRecognizer){
let tapLocation = sender.location(in: yourCollectionView)
let indexPath : IndexPath = yourCollectionView.indexPathForItem(at: tapLocation)!
var currentIndex = 0
if let cell = yourCollectionView.cellForItem(at: indexPath){
currentIndex = cell.tag
}
print("Your Selected Index : \(currentIndex)")
}
Happy Coding!!!

Resources