Collection View Cell Button not triggering action - swift

So I have a button that looks like a pencil in a collection view cell xib.
Then I have this code.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "groupsCollectionViewCellIdentifier", for: indexPath) as! GroupCollectionViewCell
//add action to the edit button
cell.editButton.tag = indexPath.row
cell.editButton.addTarget(self, action: #selector(GroupsCollectionViewController.editGroupAction), for: .touchUpInside)
return cell
}
//segue to edit group
func editGroupAction() {
performSegue(withIdentifier: "editGroupSegue", sender: self)
}
But whenever I click the edit button. Nothing is happening. I wonder what's missing.

I spent hours scouring the web for a solution to my UIButton's inside UICollectionView's not working. Driving me nuts until I finally found a solution that works for me. And I believe it's also the proper way to go: hacking the hit tests. It's a solution that can go a lot deeper (pun intended) than fixing the UICollectionView Button issues as well, as it can help you get the click event to any button buried under other views that are blocking your events from getting through:
UIButton in cell in collection view not receiving touch up inside event
Since that SO answer was in Objective C, I followed the clues from there to find a swift solution:
http://khanlou.com/2018/09/hacking-hit-tests/
--
When I would disable user interaction on the cell, or any other variety of answers I tried, nothing worked.
The beauty of the solution I posted above is that you can leave your addTarget's and selector functions how you are used to doing them since they were most likey never the problem. You need only override one function to help the touch event make it to its destination.
Why the solution works:
For the first few hours I figured the gesture wasn't being registered properly with my addTarget calls. It turns out the targets were registering fine. The touch events were simply never reaching my buttons.
The reality seems to be from any number of SO posts and articles I read, that UICollectionView Cells were meant to house one action, not multiple for a variety of reasons. So you were only supposed to be using the built in selection actions. With that in mind, I believe the proper way around this limitation is not to hack UICollectionView to disable certain aspects of scrolling or user interaction. UICollectionView is only doing its job. The proper way is to hack the hit tests to intercept the tap before it gets to UICollectionView and figure out which items they were tapping on. Then you simply send a touch event to the button they were tapping on, and let your normal stuff do the work.
My final solution (from the khanlou.com article) is to put my addTarget declaration and my selector function wherever I like (in the cell class or the cellForItemAt override), and in the cell class overriding the hitTest function.
In my cell class I have:
#objc func didTapMyButton(sender:UIButton!) {
print("Tapped it!")
}
and
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard isUserInteractionEnabled else { return nil }
guard !isHidden else { return nil }
guard alpha >= 0.01 else { return nil }
guard self.point(inside: point, with: event) else { return nil }
// add one of these blocks for each button in our collection view cell we want to actually work
if self.myButton.point(inside: convert(point, to: myButton), with: event) {
return self.myButton
}
return super.hitTest(point, with: event)
}
And in my cell class init I have:
self.myButton.addTarget(self, action: #selector(didTapMyButton), for: .touchUpInside)

Try this one on your cell
cell.contentView.isUserInteractionEnabled = false

Considering your problem I have created a demo with the details you have provided above with some minor changes.
I have modified your cellForItem method. My modified version is as below.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell : GroupCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "groupsCollectionViewCellIdentifier", for: indexPath) as! GroupCollectionViewCell
cell.editButton.tag = indexPath.row
cell.editButton.addTarget(self, action: #selector(editGroupAction(sender:)), for: .touchUpInside)
return cell
}
And the action method is written as below:
func editGroupAction(sender: UIButton) {
print("Button \(sender.tag) Clicked")
}
From your code I have modified below Details:
1) Way of declaration of UICollectionViewCell Object.
2) Way of Assigning #Selector Method to the UIButton. And at the last
3) In the action method I have print the Button tag.
With the above Changes I am getting proper result. I got the selected Index value as button tag, as assigned in code in consol. The output I am getting is as below.
Button 2 Clicked
Button 3 Clicked
Button 4 Clicked
I hope this will work for your requirement.

I was having the same issue and after using the View hierarchy, I have noticed that an additional UIView was added to the cell.
This view was above my UIButton, so touch event was not passed down to the button, the didSelectItem was triggered instead.
I solved this by using the following call:
cell.bringSubviewToFront(cell.button)
Now the event will be called.

To enable touch action on the UIButton of your Custom UICollectionCell, add the below method in your Custom UICollectionCell class.
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
var view = myButton.hitTest(myButton.convert(point, from: self), with: event)
if view == nil {
view = super.hitTest(point, with: event)
}
return view
}
If you have to cover a number of buttons, here's a way to write the same code:
class SomeCell: UICollectionViewCell {
#IBOutlet var drawButton: UIButton?
#IBOutlet var buyButton: UIButton?
#IBOutlet var likeButton: UIButton?
#IBOutlet var sayButton: UIButton?
// fix crazy Apple bug in collection view cells:
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if let drawButton = drawButton, let v = drawButton.hitTest(
drawButton.convert(point, from: self), with: event) {
return v
}
if let buyButton = buyButton, let v = buyButton.hitTest(
buyButton.convert(point, from: self), with: event) {
return v
}
if let likeButton = likeButton, let v = likeButton.hitTest(
likeButton.convert(point, from: self), with: event) {
return v
}
// etc ...
return super.hitTest(point, with: event)
}
}

I realize this ticket is pretty old, but I had the same problem, and found a different solution.
I ran Xcode with the view-debugger. While the button was sized correctly, it's superview had a width of 0 points. This would make it impossible to tap on this button, or any other subviews.
Just mentioning this, as it might be worth trying out.

If you declare your buttons programmatically you need to make sure they are set as lazy var objects to ensure self is fully defined first, before the button is initialised.
class myCell: UICollectionViewCell {
static let identifier = "myCellId"
lazy var myButton: UIButton = {
let btn = UIButton()
btn.addTarget(self, action: #selector(handleButtonPress(_:)), for .touchUpInside)
return btn
}()
// rest of cell
}

Are you assign the class to the cell and link the button with controller and also assign the identifier to the segue and also use break point to check if the func is call or not
and use segue like this
func editGroupAction() {
performSegue(withIdentifier: "editGroupSegue", sender: self)
let src = self.sourceViewController as UIViewController
let dst = self.destinationViewController as UIViewController
src.navigationController.pushViewController(dst, animated:false)
}

If you are using iOS 10.Following is working code
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! YourCellClass
cell.btnJoin.tag = (indexPath as NSIndexPath).row
cell.btnJoin.addTarget(self, action: #selector(YourViewControllerClassName.doSomething(_:)), for: UIControlEvents.touchUpInside)
}
Action
func doSomething(_ sender: UIButton) {
print("sender index",sender.tag)
}

By the way, I had to implement the hit test solution then I had this issue below:
I had a similar problem where my one of my buttons was working while another one towards the bottom of the cell was not working and it was inside a stack view. So after many hours of looking around, I found that one of the parent views (between the button and the CollectionView itself) was having a size less than the size of its subviews which in this case the touches were not reported at all since they were happening outside of the parent view... Fixed that and it's working like a charm...
To be more specific I used a compositional layout for my collection view and the view called "_UICollectionViewOrthogonalScrollerEmbeddedScrollView" which is a wrapper for the collectionView cells and the estimated size was smaller than the cell it self

Related

Doubletap recognizer for message bubbles (Messagekit)

I want to add the feature to double tap a given message bubble.
Code so far:
#objc func doubleTap(gesture: UITapGestureRecognizer) {
print("double tap called")
}
func messageStyle(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> MessageStyle {
let tapGesture = UITapGestureRecognizer(target: messagesCollectionView, action: #selector(doubleTap(gesture:)))
tapGesture.numberOfTapsRequired = 2
view.addGestureRecognizer(tapGesture)
let sender = message.sender
if sender.senderId == selfSenderEmail?.senderId {
// Self Message
return .bubbleTailOutline(.blue, .bottomRight, .curved)
}
// More if statements for groupchat color coding
return .bubbleTailOutline(.darkGray, .bottomLeft, .curved)
}
I get this Error Thread 1: "-[MessageKit.MessagesCollectionView doubleTapWithGesture:]: unrecognized selector sent to instance 0x7f94c7112a00".
If you think my post isn't clear in anyway, please let me know so I can clarify it. Thank you
You are adding UITapGestureRecognizer on view from MessagesViewController, which will attach it to the same controller view for each cell.
I suppose we are trying to get a double-tap for message cell and in order to achieve that, add UITapGestureRecognizer in the cell that you are trying to get the double tap on.
Suppose, we have DoubleTappableCell, which can be a text cell, media cell, or any other message.
class DoubleTappableCell: MessageContentCell {
lazy var doubleTapRecognizer: UITapGestureRecognizer = {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(doubleTapped))
tapGesture.numberOfTapsRequired = 2
return tapGesture
}()
var onDoubleTapped: () -> Void = {}
override init(frame: CGRect) {
super.init(frame: frame)
addGestureRecognizer(doubleTapRecognizer)
}
#objc func doubleTapped() {
onDoubleTapped()
}
}
This cell will be returned from the MessageCollectionView.
public override func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell: VideoCell = collectionView
.dequeueReusableCell(indexPath: index) else { return UICollectionViewCell() }
cell.data = anyData
cell.onDoubleTapped = {
print("DoubleTapped")
}
}
Another alternate but improved approach would be to use one UITapGestureRecognizer from ViewController to detect the indexpath of the touched cell, get the relevant cell from that index, and execute actions and view updates based on that.

How can I get the button title for each selected cell in a UICollectionView?

I have a collectionView of buttons as pictured below. I want to be able to select multiple of these cells, and in doing so pass the title of each selected button into an array of Strings.
UICollectionView - each cell has a button with a title
The UICollectionView is in WordViewController class
class WordViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout
And the UICollectionViewCell is in it's own file.
import UIKit
class WordCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var wordView: UIButton!
#IBAction func buttonTapped(_ sender: UIButton) {
if wordView.isSelected == true {
wordView.isSelected = false
wordView.backgroundColor = UIColor.blue
}else {
wordView.isSelected = true
wordView.backgroundColor = UIColor.green
}
}
}
I'm very new to Swift and I have been trying to find an answer to this for days, but I can't figure it out. I suspect I may have to use indexPathsForSelectedItems but I have tried this and can't get it working.
func indexSelected () {
let collectionView = self.collectionView
let indexPath = collectionView?.indexPathsForSelectedItems?.first
print(indexPath!)
let cell = collectionView?.cellForItem(at: indexPath!) as? WordCollectionViewCell
let data = cell?.wordView.currentTitle
print(data!)
}
I'm not sure if I have something fundamental wrong in the way I have set up my CollectionView or if it is something to do with me using buttons within the CollectionViewCells.
Any help would be very appreciated.
This is one way you could do it. First get the indexPaths for the selected cells. Then loop through the indexPaths and get your cell for each IndexPath (cast them as your custom CollectionViewCell to access your button). Now you can append each title to an array to save them.
var titleArray = [String]()
guard let selectedIndexPaths = collectionView.indexPathsForSelectedItems else { return }
for indexPath in selectedIndexPaths {
if let cell = collectionView.cellForItem(at: indexPath) as? WordCollectionViewCell {
self.titleArray.append(cell.yourButton.titleLabel?.text)
}
}
Welcome to SO. This sounds a bit like an X/Y problem: A case where you are asking about how to implement a specific (often sub-optimal) solution rather than asking about how to solve the problem in the first place.
You should not treat the views in your collection view as saving data. (buttons are views.)
You should use the button to figure out the indexPath of the cell the user tapped and then look up the information in your data model.
You should set up an array of structs (or an array of arrays, if your collection view is in sections of rows.) Each of those structs should contain the current settings for a cell.
Your collectionView(_:cellForItemAt:) method should use the array of structs to configure your sell for display.
As the user taps buttons and selects cells, you should update the struct(s) at the appropriate IndexPath(s) and then tell the collection view to update those cell.
If you need to do something with the selected cells, you should ask the collection view for an array of the selected cells, you should use those IndexPaths to index into your model array and fetch the struct for each IndexPath, and then look up teh data you need.
EDIT:
You can use a really simple extension to UICollectionView to find the indexPath of any view inside your collection view (and a button is a view, as mentioned...)
extension UICollectionView {
func indexPathForCellContaining( view: UIView) -> IndexPath? {
let viewCenter = self.convert(view.center, from: view.superview)
return self.indexPathForItem(at: viewCenter)
}
}

Drag from a collection view cell works on iPad simulator but not on iPhone simulator or real device in Swift 4

I am using the new drag and drop api in swift 4. I need to drag a cell by long tapping on it and dropping the image on the view controller's view. This is dragging and dropping in the same application because it needs to work on the iPhone, and this feature only works on the phone in the same app. I use a real device for testing what I write and I could not figure out why I cannot drag a cell once I have tapped on it. But running the simulator on iPad and ...it works, I can drag it. I have gone over apple's documentation and they specify that the drag item's appearance can be configured during the drag, but the default is that the whole cell will be dragged if no custom implementation of the delegate's function is present or nil is returned; so it should still work, it does it in the simulator on iPads but not on simulated iPhones or the real one. Code listing below. Maybe someone has gone over this already and knows how to help me. Thank you.
Only the relevant bits:
class DefineRoomPropertiesVC: UIViewController {
//MARK: - Init.
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setupTopMenuBar()
setupViews()
topMenuCollectionView.dragDelegate = self
}
fileprivate let topMenuCollectionView: TopMenuBarCollectionView = {
let layout = UICollectionViewFlowLayout()
let collectionView = TopMenuBarCollectionView(frame: .zero, collectionViewLayout: layout)
return collectionView
}()
}
extension DefineRoomPropertiesVC: UICollectionViewDragDelegate {
func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] { // called when a drag is initiated.
let image = topMenuCollectionView.imagesForTopSectionCell[indexPath.item]
let itemProvider = NSItemProvider(object: image)
let dragItem = UIDragItem(itemProvider: itemProvider)
return [dragItem]
}
func collectionView(_ collectionView: UICollectionView, dragPreviewParametersForItemAt indexPath: IndexPath) -> UIDragPreviewParameters? {
return nil
}
Maybe you forgot to implement some delegate's methods. Here is the great tutorial: Coding for iOS 11: How to drag & drop into collections & tables
Make sure you set dragInteractionEnabled flag to true
collectionView.dragInteractionEnabled = true
Pretty stupid, but Apple has enabled the drag interaction for iPad but set it to false on iPhone as a default value.
You would be adding your UIDragInteraction to your UIView. Make sure that it is enabled by setting the value to true. In my code, it looks as follows.
let dragInteraction = UIDragInteraction(delegate: self)
dragInteraction.isEnabled = true
dragView.addInteraction(dragInteraction)

Does the keyboard for a UITextField have to take up the whole screen?

It seems that the keyboard doesn't have to take up the whole screen, check UPDATE in the Question section of my post. Thanks.
Description
Use UITextField to place a full-screen keyboard on the screen.
reference
I've set up a UISplitViewController and I would like the RootViewController (aka MasterViewController) to have the UITextField with the Keyboard showing. Then I would like results of the search on the right (in the "ResultViewController" (UIViewController).
The idea is when the user types, results are proposed.
What I've tried:
I first added a UITextField to my RootViewController via the storyboard but that took up the whole screen when I activated the keyboard via textField.becomeFirstResponder().
I figured if I use a UIAlertController I'd get by this issue, but the keyboard still takes up the whole screen.
class RootViewController: UIViewController {
override func viewDidLoad() {
let alertController = UIAlertController(title: "Search", message: "Search for something!.", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addTextFieldWithConfigurationHandler({(textField: UITextField!) in
textField.placeholder = "Search"
})
self.addChildViewController(alertController)
alertController.view.frame = self.view.frame
self.view.addSubview(alertController.view)
}
}
Question:
When using a UISplitViewController how can I get the keyboard to only stay in it's RootViewController and not take up the whole screen?
UPDATE: It appears this has been implemented in the Netflix app on the new apple tv. The keyboard is on the top and takes up the whole width. The bottom is divided into two sections. On the left, proposed word results and on the right a collection view of video covers of possible videos. Everything is updated as the user types.
If this is considered bad design for Apple TV, then feel free to point out why.
Screen shot:
This is what I currently get. The text box opens a keyboard that takes up the whole screen.
Presenting a keyboard only on a portion of the screen is not possible with the built-in SDK methods.
A UIKeyboard is presented on the application's window, not on any of its subviews. To accomplish your desired behavior, use reflection to get a reference to the UIKeyboard object on your application's UIWindow (by iterating through the window's subviews), and change its frame to match the width of your RootViewController.
To get started, you can look at the private UIKeyboard.h tvOS header here. I should note that Apple may have code in place to disable resizing of the keyboard (like in willMoveToWindow: or didMoveToWindow for example). This is undefined behavior and your milage will vary, if it even works at all.
You have deleted your comment on my answer about the Netflix app, but as shirefriendship says in their answer, Netflix probably uses a TVML template. You could go that route and build a hybrid tvOS/TVML app. Additionally, you could also manually build a keyboard yourself with a UICollectionView in your RootViewController.
Netflix is using TVML Templates to implement their search instead of UIKit. You can accomplish the same aesthetic as Netflix using the searchTemplate. You can learn to mix TVML and UIKit here. Unfortunately the searchTemplate is not customizable enough to conform to your desired layout. There is currently no way to implement your specific layout for the Apple TV.
Introduction:
I was finally able to implement this without having to use TVML templates. The final solution looks something like this:
The general idea is to create a UICollectionViewController with a UICollectionViewCell. Then to programmatically add a keyboard and add it to your TabViewController via your AppDelegate.
How to implement this search view with results:
Step 1: Storyboard and Controller creation
Open your storyboard and create a UICollectionViewController (with a custom class "SearchResultViewController") that is not attached to your TabViewController.
Within it create a your UICollectionViewCell with whatever labels and images you want. UICollectionViewCell should have a custom class called "VideoSearchCell".
Your SearchViewController should have nothing else inside.
Step 2: Adding SearchViewController to TabViewController and implementing keyboard via AppDelegate programmatically
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
override init() {
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
if let tabController = window?.rootViewController as? UITabBarController {
tabController.viewControllers?.append(configueSearchController())
}
return true
}
//... standard code in-between
func configueSearchController() -> UIViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
guard let searchResultController = storyboard.instantiateViewControllerWithIdentifier(SearchResultViewController.storyboardIdentifier) as? SearchResultViewController else {
fatalError("Unable to instatiate a SearchResultViewController from the storyboard.")
}
/*
Create a UISearchController, passing the `searchResultsController` to
use to display search results.
*/
let searchController = UISearchController(searchResultsController: searchResultsController)
searchController.searchResultsUpdater = searchResultsController
searchController.searchBar.placeholder = NSLocalizedString("Enter keyword (e.g. Gastric Bypass)", comment: "")
// Contain the `UISearchController` in a `UISearchContainerViewController`.
let searchContainer = UISearchContainerViewController(searchController: searchController)
searchContainer.title = NSLocalizedString("Search", comment: "")
// Finally contain the `UISearchContainerViewController` in a `UINavigationController`.
let searchNavigationController = UINavigationController(rootViewController: searchContainer)
return searchNavigationController
}
}
Once you've added the basic skeleton of your SearchResultViewController you should be able to see the keyboard on the top of the Search view when you run your project.
Step 3: Handling text input and updating results
You'll notice that in my filterString I use a class called ScoreVideo and a StringSearchService. These are just classes I use to filter my Video list (aka: self.vms.videos).
So in the end, just take the filterString, create a new filtered list and reload your collection view.
import UIKit
import Foundation
class SearchResultViewController: UICollectionViewController, UISearchResultsUpdating {
//private let cellComposer = DataItemCellComposer()
private var vms: VideoManagerService!
private var filteredVideos = [ScoreVideo]()
static let storyboardIdentifier = "SearchResultViewController"
var filterString = "" {
didSet {
// Return if the filter string hasn't changed.
guard filterString != oldValue else { return }
// Apply the filter or show all items if the filter string is empty.
if self.filterString.isEmpty {
self.filteredVideos = StringSearchService.start(self.filterString, videos: self.vms.videos)
}
else {
self.filteredVideos = StringSearchService.start(self.filterString, videos: self.vms.videos)
}
self.collectionView?.reloadData()
}
}
override func viewDidLoad() {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
self.vms = appDelegate.getVideoManagerService()
}
// MARK: UICollectionViewDataSource
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print("count..\(filteredVideos.count)")
return filteredVideos.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// Dequeue a cell from the collection view.
return collectionView.dequeueReusableCellWithReuseIdentifier(VideoSearchCell.reuseIdentifier, forIndexPath: indexPath)
}
// MARK: UICollectionViewDelegate
override func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
guard let cell = cell as? VideoSearchCell else { fatalError("Expected to display a `VideoSearchCell`.") }
let item = filteredVideos[indexPath.row]
cell.configureCell(item.video)
}
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
dismissViewControllerAnimated(true, completion: nil)
}
// MARK: UISearchResultsUpdating
func updateSearchResultsForSearchController(searchController: UISearchController) {
print("updating... \(searchController.searchBar.text)")
filterString = searchController.searchBar.text!.lowercaseString ?? ""
}
}
If something is unclear, feel free to ask some questions. I most likely forgot something. Thanks.
Answer inspired from apple sample code

How would I unhide a button if user performs segue in swift?

I have a button inside a cell (PFQueryTableViewController) that is hidden and I want to unhide it when the user performs a certain segue that I call programatically.
When the user taps the cell it segues to a view controller which displays the contents of the cell full screen... I want the button to unhide in this cell when the segue is called so when the user goes back to the table of cells they can see it on the cell they just tapped.
How can I do this?
Edit after questions:
inside cellRowForIndexPath I have the following for the button
cell.myButton.tag = indexPath.row
cell.myButton.addTarget(self, action: "pressed:", forControlEvents: UIControlEvents.TouchUpInside)
cell.myButton.hidden = true
And the segue itself carries information from the cell (stored in Parse backend) across to FullPostViewController from AllPostsTableViewController. The code for that is this (would I call the unhide in here somewhere?):
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("showFullPost", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showFullPost" {
let indexPath = self.tableView.indexPathForSelectedRow
let fullPostVC = segue.destinationViewController as! FullPostViewController
let object = self.objectAtIndexPath(indexPath)
fullPostVC.post = object?.objectForKey("postContent") as? String
let likeCount = object!.objectForKey("likedBy")!.count
fullPostVC.likesCounted = String(likeCount)
self.tableView.deselectRowAtIndexPath(indexPath!, animated: true)
}
}
(Answer thoroughly edited after thorough edit of question)
One possible solution follows below.
Since you mention table cells (each containing a button; I'll assume UIButton), I assume you populate your table view cells with UITableViewCell objects; some fancy subclass to the latter. In this class:
If you haven't already, create an #IBOutlet from your button as a property in this class.
Overload the method setSelected(...) to un-hide your button in case the UITableViewCell is selected (which will precede the segue)
Hence, in your UITableViewCell subclass, you should be able to do something along the lines:
// ...TableViewCell.swift
Import UIKit
// ...
class ...TableViewCell: UITableViewCell {
// Properties
#IBOutlet weak var button: UIButton!
// button contained in UITableViewCell
// ...
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// If table cell is selected (after which segue will follow),
// un-hide button.
if (selected) {
button.hidden = false
}
}
}
Hopefully this will achieve your goal.