How do I tell which button called another view in swift 4? - ios

I want to know which button called the second view which displays a list of the type of items. The tableViewCell contains an array of all the items. For example, if the user taps on burgers he gets a list of all the burger items. I have connected each button to the second view individually but it seems like there has to be a better way like connecting it to the touchButton method that all buttons are connected to but I'm not sure how to do this. Also, should the array of items be in tableViewController or is tableViewCell fine?

First of all instead of giving each button segue for same view, i recommend you to use only one segue.
One approach is to simply use a indicator int or string depending upon your logic in items table view and assign it accordingly in prepare for segue method by getting destinationVC. And handle the indicator on list items view on loading. (in this approach you have only one segue and you will be able to perform the work).
As far as table view approach is concerned. use tableview for list of items and use tableViewCell for individual items.

In theory :
If you are moving onto the next ViewController from current , you can create a variable inside the next View Controller and while moving from current VC to next, you can fetch the name of the Button inside the #IBAction method and create instance of next VC and access that variable (created earlier) and assign the name of that button to that variable
Code :
class CurrentViewController: UIViewController {
// Your other code goes here
#IBAction func actionButtonTapped(_ sender: UIButton) {
// Here we fetch the name of the button tapped
let nameOfButtonTapped = sender.titleLabel!.text
// Here we create instance of NextViewController
let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "#yourNextVCIdentifierHere") as! NextViewController
// Here we assign the name of the button tapped to the variable of NextViewController so we can access it there
nextVC.buttonNameThatWasClicked = nameOfButtonTapped
self.present(nextVC, animated: true, completion: nil)
}
}
class NextViewController: UIViewController {
var buttonNameThatWasClicked: String?
override func viewDidLoad() {
super.viewDidLoad()
print(buttonNameThatWasClicked!)
}
}
Here, we can connect All the Buttons to a single #IBAction by control-dragging all the buttons to the name of the #IBAction method

Related

How to pass data from First ViewController directly to the Third View Controller using segue?

I was able to perform the task of passing value from one view controller to another view controller. I had a textField and submit button in one view controller and in another I had a label, after I gave input to the textField, I was able to replace the label text with textField's text.
But now what I am trying is that when I click on submit button in first view controller , it should move to second view controller (performSegue) and at the same time it should pass the value to the third view controller..
But I am getting an error if I do that, is there a simple way to pass values from one view controller to third view controller where I can skip "n" number of view controllers which come in between the target and destination?
Here's an example:
Suppose there are three viewControllers, first viewController has a
textField and a submit button, second view Controller has a "NEXT"
button and third View Controller has a label.
When I enter the textField and click on submit , it should submit the textField.text to third View Controller and should perform segue to second view controller,
now when I am on second view controller it'll show NEXT button. After I click on next, it'll take me to third View controller where it'll show me the first View COntroller's textField's text in the label...
My question is, how to do that? I went through a lot of youtube videos of implementing segues but nobody talked about how to pass data from one view controller to another view controller by skipping some view controllers.
I hope you do understand my question.
Your time and help will be highly appreciated!
Thank You
assign storybordID to your controller for ex here i have assigned "HomeVC" (it would be greate if you assign class name and storybordid same)
let objthirdController = self.storyboard?.instantiateViewController(withIdentifier: "thirdControllerStoerybordID") as! thirdControllerclassname
objthirdController.variable = self.variable
self.navigationController?.pushViewController(objthirdController, animated: true)
The way you are able to perform the task of passing value from one view controller to another view controller.
Repeat the same when you are in next controller, till you reach your destination view controller.
you should use Notification Observer Design Pattern but its better to pass it throw the view controller instead of passing directly to destination ViewController but here is the solution:
struct NotificationKeys {
static let myKey = "myKey"
}
class SourceViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func yourButtonPressed(_ sender: UIButton) {
let name = Notification.Name(rawValue: NotificationKeys.myKey)
NotificationCenter.default.post(name: name, object: nil)
performSegue(withIdentifier: "identifier", sender: self)
}
}
you can pass with object too, its so simple with object too,
just search pass data with NotificationCenter in google if you don't understand the code ;)
class DestinationViewController: UIViewController {
deinit {
NotificationCenter.default.removeObserver(self)
}
#IBOutlet weak var yourLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
createObserver()
}
func createObserver() {
NotificationCenter.default.addObserver(self, selector: #selector(updateLabel(notification:)), name: Notification.Name(rawValue: NotificationKeys.myKey), object: nil)
}
#objc func updateLabel(notification:NSNotification) {
let isText = notification.name.rawValue == NotificationKeys.myKey
let text = isText ? "\(isText)" : ""
yourLabel?.text = text
}
}

Displaying text entered into textfield (in second view controller) in a label on first view controller?

I have been trying a challenge out alone in Swift to do programmatically - with no use of storyboards.
My first view controller has a label and a button to go to the second view controller.
I created a navigation controller within the app delegate file, and then push to the second view controller when the button is pressed.
The second view controller has a textfield, a button to save the text, and a button to go back to the first view controller.
The UI is fine, but I cannot figure out how to save the text that is entered into the textfield which is on the second view controller, and then display this text in the label in the first view controller.
Can someone give me a clue as to how to do this?
Currently in my button going back to the first view controller I have this:
func handleBackToVC1() {
self.navigationController?.popViewController(animated: true)
}
Is this where I pass the data that is in the textfield and display it in the label?
Also, should I give the label some text to start off with? But which would then get changed to what was entered into the textfield?
use protocol delegate for passing data from SecondViewController to FirstViewController
protocol TextFieldDataDelegate: class {
func saveText(_ text: String)
}
class SecondViewController: UIViewController {
weak var delegate: TextFieldDataDelegate?
//on save button tap call the delegate method
delegate?.saveText(textField.text)
}
//set FirstViewController as delegate for TextFieldDataDelegate protocol
class FirstViewController: UIController, TextFieldDataDelegate {
// when you create instance of SecondViewController assign the delegate as self
let secondVC = SecondViewController()
secondVC.delegate = self
//in saveText set label text as passed from SecondVC
func saveText(_ text: String) {
self.textLabel.text = text
}
}
Note: There are many similar questions like this, always search before asking the question. Thanks

How to pop back to a TableViewController?

I start of with a tableViewController that has a list of names. When the user taps on a name, they are segued to a view controller.
While in that viewController the user may press a button that will take them to another table view Controller.
The layout is like this:
TableViewController(1) -> ViewController -> TableViewController(2)
My question is, how can I pop back to the first TableViewController from the Second TableViewController.
My rootViewController is my signIn View controller so I cannot pop back to root.
You can run this to pop to your rootViewController:
self.navigationController?.popToRootViewController(animated: true)
Update:
Since your rootViewController is not where you want to end up then you can iterate through your controllers and pop to a specific one:
for controller in self.navigationController!.viewControllers {
if controller.isKind(of: TableViewControllerOne.self) {
self.navigationController!.popToViewController(controller, animated: true)
break
}
}
Instead of TableViewControllerOne.self update to your desired controller.
If you're familiar with segues, you can implement an unwind segue. That would give you the added benefit of passing information back to TableViewController(1) if you needed to. To make that work in TableViewController1 you would add some code that looked like:
#IBAction func unwind(fromTableVC2 segue: UIStoryboardSegue) {
if (segue.source is TableVC2) {
if let svc = segue.source as? TableVC2 {
// pass information back
}
}
}
Then in your storyboard you would go to where you have your TableVC2 and drag the yellow VC circle to the exit and choose the function we created above. Name the segue (for this example we'll call it "UnwindToTableVC1"), and then somewhere in TableVC2 add the code:
func setVariableToPassBack () {
// Set up variables you want to pass back
performSegue(withIdentifier: "UnwindToTableVC1", sender: self) }
And that will take you back to your chosen destination with any information you wanted to pass back.
If you don't want to pass anything back, you really just need call the below line in your TableVC2:
performSegue(withIdentifier: "UnwindToTableVC1", sender: self)

Passing Data from to another View Controller without changing view (Swift)

I have a searchViewController where I search for users and UITableView gets updated dynamically with user information. The cell for the UITableView is custom - it has a UIImage, the usernameLabel, and a button called "Add".
What I want is that if the user clicks on the add button of the cell, it should pass the user information on that cell (image and username) to another view controller that has a UITableView that is a friend list.
However, so far the only way I know is by using performSegue to pass the data on to the other viewController holding the friendlist UITable. But by this method, every time I click the add button it segues to the other view controller which I don't want. I want it to stay on the searchViewController when the add button is clicked - I only want the data to be passed.
Is there any way I can do this? Is using NSUserDefaults advisable for passing data of this sort?
For simplicity I will use FriendListVC and AddVC
If you are going to your AddVC from FriendListVC via a bar button item or something and your stack looks like:-
FriendListVC -> AddVC
There are two approaches you can use:-
1) Create a delegate of your friendListVC in your addVC and modify the friendListVC datasource on any changes there
2) Or, and I recommend this approach, just reload your FriendListVC datasource on it's viewWillAppear. viewWillAppear will get called even if you navigate back. Thus even if you add a deleteVC in the future and navigate back, the viewWillAppear will perform the updates and it will be independent of any other VC
Hope that helps
Use delegate for passing data between view controllers. you can find this useful
Passing data between 2 UIViewController using delegate and protocol
you can use NSUserDefaults but delegate pattern is better than this.
You can use callback method best and easy way to pass data one controller to another
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
let viewControllerB = segue.destinationViewController as! ViewControllerB
viewControllerB.callback = { message in
//Do what you want in here!
}
}
In ViewControllerB:
var callback : (String -> Void)?
#IBAction func search(sender: AnyObject) {
callback?("Pass data to view controller1")
self.dismissViewControllerAnimated(true, completion: nil)
}
The easiest way to do this is by making an instance of the view controller that you want to pass data to, in the current view controller. I will write you a sample code for this.
class yourTableViewController: UITableViewController {
var controllerToPassData: UIViewController()
func clickTableButton(sender: UIButton) {
controllerToPassData.count += 1
}
}
class controllerwhereDataisPassed: UIViewController {
var count: Int!
}
Pick the instance of the controller where you want to pass data to from the navigationController stack and use this code.

How to send values to a parent view controller in Swift

I am working on a settings view controller screen for my iOS app written in swift. I am using a navigation controller to run the main settings table view which shows the cell titled, "Input Method." The current method is listed on the right of the cell. They can click the cell to go to the next view controller where they can select the input method that they'd like.
From here, there are two sections. The first is the input method to choose (touchscreen or joystick). The second section is joystick specific on whether or not the person is a lefty or righty. I don't want to have the vc unwind when they choose one box because they may choose one in another section too.
My question: How can I update the text field in the parent controller from the child controller.
Problems I'm having for optional solutions:
let parentVC: UIViewController = (self.navigationController?.parentViewController)!
parentVC.inputMethod.text? = cellSelected // This doesn't work because it cannot find the label inputMethod.
viewDidLoad() will cause a lag and the user sees the old method before it changes.
I cannot find out how to run a segue when someone clicks the back button at the upper left hand side in the navigation controller, since the navigation controller controls the segue.
It is not a good idea to cast the parent view controller, even when you are sure which class represents. I'll do it with a protocol:
In the child controller add a protocol like:
protocol ChildNameDelegate {
func dataChanged(str: String)
}
class ChildClass {
weak var delegate: ChildNameDelegate?
func whereTheChangesAreMade(data: String) {
delegate?.dataChanged(data)
}
}
And in the parent:
class ParentClass: ChildNameDelegate {
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let segueId = segue.identifier else { return }
switch segueId {
case "childSegue":
let destVC = segue.destinationViewController as! ChildClass
destVC.delegate = self
break
default:
break
}
}
// Child Delegate
func dataChanged(str: String) {
// Do whatever you need with the data
}
}
You need to cast the parentViewController to whatever custom class it has. For example, if the parent has the class ExampleParentController, you would write:
let parentVC = (self.navigationController?.parentViewController)! as! ExampleParentController
parentVC.inputMethod.text? = cellSelected
I found a solution here: Modifing one variable from another view controller swift
http://www.raywenderlich.com/115300/swift-2-tutorial-part-3-tuples-protocols-delegates-and-table-views
Instead of trying to access the view controller directly (which would be easier if it weren't returning a nil for the view controller) you can use a delegate method to adjust the variables.
The delegate worked like a charm!

Resources