How would I unhide a button if user performs segue in swift? - 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.

Related

Retain The State Of On Off Button In A UITableViewCell - Swift

I have been searching through many posts on SO but couldn't find an answer to this one.
I have a Table view listing various items. Each cell in the table view has a button that swaps an image around when clicked on, effectively working as an "on" or "off" button to show a user which items in the list they have selected. I have a variable inside my custom Cell Prototype class which stores a value of true or false which is updated every time the button is clicked on.
There is a "Done" button in the Table View that when tapped on calls an unwind Segue to go back to the first View Controller.
When the user taps on the Enter Table View button (on the first View Controller) to display the Table the buttons all go back to their default state, am guessing because each time the segue to the Table View Screen happens it creates a new instance of the Table to be displayed.
What I'm trying to achieve is that the state of the button (either on or off) is retained when going back into the Table screen. I've tried for a while sending an Integer value back from the TableCell Class (using a delegate) to the first View controller and then passing that value back into the Table View controller when the forward segue is called in order to have a "retained from the previous state value" that can be compared against when the cells are created to indicate if a button had been clicked or not. Couldn't get it to work though to save the state of the buttons. The list of Items in the Table will also change depending on what a user adds.
Some Screen shots and the code are below. The code hasn't got the delegate i was trying included (as it didn't work) but if its needed I will edit the post to include it. Any help would be hugely appreciated. Many Thanks!!
Code I have so far is:
//Main View Controller//
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
//segue to the Table View Screen
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "EnterTableView" {
let newTableView = segue.destination as! TableViewController
}
}
// Unwind Segue Called on Exit From Table View
#IBAction func unwindToMainViewController (_segue:UIStoryboardSegue) {
}
}
// Table View Controller //
class TableViewController: UITableViewController {
var dataArray = ["A", "B", "C", "D"]
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
//create one section for table
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//create number of rows based on the number of items in the dataArray set above
return dataArray.count
}
// an array that will contain all the cells
var cellArray = [UITableViewCell] ()
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//create a new cell based on the cell class "TableViewCell"
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as? TableViewCell
// variable to contain a single element from the dataArray - updates every time a new cell is created
let dataArrayForCells = dataArray [indexPath.row]
//set cell label text to show the value from the dataArrayForCells
cell!.label.text = dataArrayForCells
cellArray.append(cell!)
return cell!
}
// Table Cell Class//
class TableViewCell: UITableViewCell {
#IBOutlet weak var label: UILabel! // label to hold display some text
#IBOutlet weak var buttonImage: UIImageView! //image for button
var buttonClicked = true //variable to contain weather the has been clicked
//if button is tapped on run the below
#IBAction func aButton(_ sender: Any) {
//if button is clicked is true, swap image to red ("on") button, set buttonClicked value to false
if buttonClicked {
buttonImage.image = #imageLiteral(resourceName: "Rec Button Red")
buttonClicked = false
}
// if buttonClicked value is false swap image to grey ("off") button set buttonClicked value back to true
else {
buttonImage.image = #imageLiteral(resourceName: "Rec Button Grey")
buttonClicked = true
}
}

Dissmiss UITableViewController from button in TableViewCell

I have a UITableViewController that has a header view class with a UIButton in it that I've linked up in interface builder. I've got it working fine so that when you tap the button the code fires.
However, I have no idea what to write to dismiss the table view when you tap this button.
class headerCell: UITableViewCell {
#IBAction func exit () {
print("got pressed")
// tried: MyTableView().dismiss(animated: true, completion: nil)
// But did not work, did nothing?
}
}
class MyTableView: UITableViewController {
// All the code for the tableView is here...
}
MyTableView().dismiss(animated: true, completion: nil)
This makes a brand new table view controller and dismisses it. Since it was never even presented, this does nothing
You need to dismiss the one that contains the cell.
This is one way: https://stackoverflow.com/a/50334803/3937
But I recommend adding a weak reference to the header cell to the MyTableView and setting it on construction
Also, MyTableView is a ViewController, not a view. So, MyTableViewController is a better name.
After experimenting with the various answers, I've found that creating an IBAction is not the best way to do this, and instead I've simply added an IBOutlet for the button, then done this in the TableViewController:
#objc func exit () {
dismiss(animated: true, completion: nil)
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: "headerCell") as! headerCell
cell.exitButton.addTarget(self, action: #selector(exit), for: .touchUpInside)
return cell
}

Perform a segue programmatically

Hi I'm trying to perform a segue programmatically without the Storyboard. Currently I have this as my code:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "popOutNoteExpanded" {
let vc = segue.destination as! ExpandedCellViewController
let cell = sender as! AnnotatedPhotoCell
sourceCell = cell
vc.picture = cell.imageView.image
print("button pressed")
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
performSegue(withIdentifier: "popOutNoteExpanded", sender: indexPath)
}
When I click on the collection view cell it's saying that:
has no segue with identifier 'popOutNoteExpanded'.
Not sure how to perform my custom animated transition.
To trigger a segue programmatically, you have to follow steps:
1. Set it up in Storyboard by dragging your desired segue between two view controllers and set its identifier (for example, in your case is "popOutNoteExpanded") in Attributes Inspector section.
2. Call it programmatically
performSegue(withIdentifier: "popOutNoteExpanded", sender: cell)
Please check if you set its identifier correctly or not.
Besides, in your above code, you put an incorrect sender.
In your prepare() method, you use the sender as a UITableViewCell, but you call performSegue() with sender as a IndexPath.
You need a cell by calling:
let cell = tableView.cellForRow(at: indexPath)
And then you can perform a segue:
performSegue(withIdentifier: "popOutNoteExpanded", sender: cell)
Segues are components of storyboard. If you don't have a storyboard, you can't perform segues. But you can use present view controller like this:
let vc = ViewController() //your view controller
self.present(vc, animated: true, completion: nil)
Additional to the correct answer, please be aware that if you are in a navigation stack (say, you are in a Settings page and want to segue to an MyAccountVC) you should use:
let vc = MyAccountVC()
self.navigationController?.pushViewController(vc, animated: true)
If the navigated VC appears with a transparent background during the transition, just set the backgoundColor of it to .white.
In my case I was presenting a TableViewController, without a segue defined, and found it was necessary to instantiate from the storyboard otherwise tableViewCells couldn't be dequeued in cellForRowAt.
let vc = (storyboard.instantiateViewController(withIdentifier: "YourTableViewController") as? YourTableViewController)!
self.navigationController!.pushViewController( vc, animated: true)

I want to send data when I tap a button in tableView Cell

I am implementing a commentView for my app. I have a main view which is tableview contains picture and a button to go comment view.
I want that when user tap comment button in table view, view shows comment view and pass PFObject by prepareforSegue method.
now comment button works, but I have an error from prepareforsegue
here is my code.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "mainToComment") {
let destViewController : CommentVC = segue.destinationViewController as! CommentVC
destViewController.parentObjectID = parentObjectID
let selectedRowIndex = self.tableView.indexPathForSelectedRow
destViewController.object = (postsArray[(selectedRowIndex?.row)!] as? PFObject)
and here is my how my button works.
#IBAction func commentButtonTapped(sender: AnyObject) {
let button = sender as! UIButton
let view = button.superview!
let cell = view.superview as! MainTVCE
let indexPath = tableView.indexPathForCell(cell)
parentObjectID = postsArray[(indexPath?.row)!].objectId!!
when I debug, selectedRowIndex has no value(nil)
I think it cause of I tap button instead of cell.
How can I set indexPath for this?
or
How can I make it work?
I don't know name of your main TableViewCell view controller. Assume that, I name this view controller is MainTableViewCell.
I create a closure in MainTableViewCell:
var didRequestToShowComment:((cell:UITableViewCell) -> ())?
When button comment is tapped:
#IBAction func commentButtonTapped(sender: AnyObject) {
self.didRequestToShowComment?(self) // self is this UITableViewCell
}
In table cellForRowAtIndex... of your main view controller.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
...
mainTableViewCell.didRequestToShowComment = { (cell) in
let indexPath = tableView.indexPathForCell(cell)
let objectToSend = postsArray[indexPath.row] as? PFObject
// Show your Comment view controller here, and set object to send here
}
...
return cell
}

Trigger Segue from UIButton in TabeViewCell

I have prototype cell and in this cell there is an UIButton; so I need to perform a segue from the button to other controller, not from the cell. I tried to create an Outlet #IBOutlet var button: UIButton! and use performSegueWithIdentifier() method
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
self.performSegueWithIdentifier("toSecondController", sender: button)
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
but I have no idea how to set the prepareForSegue() method... i tried this
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "toSecondController"
{
if let indexPath = sender as? UIButton//tableView.indexPathForSelectedRow()
{
let controller = segue.destinationViewController as! CoriViewController
controller.coriSquadra = DataManager.sharedInstance.arrayCori[indexPath.row]
}
}
}
I also read that a solution would be implement a protocol, but I'm a beginner and I need a step by step guide.
Hope someone can help me!
Your on the right track. In your tableviewcontroller define
#IBAction func clicked(){
self.performSegueWithIdentifier("toSecondController", sender: button)
}
You can keep the
tableView.deselectRowAtIndexPath(indexPath, animated: true)
line in your didSelectRowAtIndexPath. Don't forget to connect your ibaction to the button in your storyboard as well.