Passing the UISlider value to the previous page [closed] - ios

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 19 hours ago.
Improve this question
I'm making a Pomodoro app and adjusting the focus time using UISlider.I can access the UISlider value on the screen where I define the UISlider. But I want to switch to the previous screen. I failed. My first page is ViewController(), my second page is SettingsVC().
It's my 5th month in software.
Very happy if you help.
Firs Page
import UIKit
class ViewController: UIViewController {
let actionButton = SFActionButton()
var minutesLabel = SFTimeLabel(text: "25")
let secondsLabel = SFTimeLabel(text: "00")
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
}
#objc func controll(){
print("Slider Value : \(SettingsVC().focusTimeSlider.value)")
print("Working")
}
#objc func settingsAction(){
let rootVC = SettingsVC()
let navVC = UINavigationController(rootViewController: rootVC)
navVC.modalPresentationStyle = .fullScreen
self.present(navVC, animated: true, completion: nil)
}
}
This code page is my first page.
Second Page
import UIKit
class SettingsVC: UIViewController {
//MARK: - Sliders
var focusTimeSlider = UISlider()
let shortBreakTimeSlider = UISlider()
let longBreakTimeSlider = UISlider()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
title = "Settings"
}
//MARK: - Done Button
func addCloseButton(){
let button = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(onClose))
navigationItem.rightBarButtonItem = button
}
#objc func onClose(){
self.dismiss(animated: true, completion: nil)
print("Focus Time : \(Int(focusTimeSlider.value))")
print("Short Break Time : \(Int(shortBreakTimeSlider.value))")
print("Long Break Time : \(Int(longBreakTimeSlider.value))")
}
//MARK: - Slider Actions
func layoutFocusTimeSlider(){
focusTimeSlider.addTarget(self, action: #selector(focusSliderValueChanged(sender:)), for: .valueChanged)
}
#objc func focusSliderValueChanged(sender: UISlider){
focusTimeSliderValueLabel.text = String(Int(focusTimeSlider.value))
}
func layoutShortBreakTimeSlider(){
shortBreakTimeSlider.addTarget(self, action: #selector(shortSliderValueChanged), for: .valueChanged)
}
#objc func shortSliderValueChanged(){
shortBreakTimeSliderValueLabel.text = String(Int(shortBreakTimeSlider.value))
}
func layoutLongBreakTimeSlider(){
longBreakTimeSlider.addTarget(self, action: #selector(longSliderValueChanged), for: .valueChanged)
}
#objc func longSliderValueChanged(){
longBreakTimeSliderValueLabel.text = String(Int(longBreakTimeSlider.value))
}
}
This code page is my second page.

I have two solutions
First solution:
You can add a new function in the first ViewController
func sliderValue(value: CGFloat) {
// add what you want to do here with the value
}
then you add variable in the settings view will hold the parentView instance
like this
weak var parentView: UIViewController?
and when you presenting the settings view controller you assign the parent view controller to the parentView instance before presenting
#objc func settingsAction(){
let rootVC = SettingsVC()
rootVC.parentView = self
let navVC = UINavigationController(rootViewController: rootVC)
navVC.modalPresentationStyle = .fullScreen
self.present(navVC, animated: true, completion: nil)
}
then before dismissing the settings view you call the function sliderValue
#objc func onClose(){
if let parentView = parentView as? ViewController {
parentView.sliderValue(value: focusTimeSlider.value)
}
self.dismiss(animated: true, completion: nil)
print("Focus Time : \(Int(focusTimeSlider.value))")
print("Short Break Time : \(Int(shortBreakTimeSlider.value))")
print("Long Break Time : \(Int(longBreakTimeSlider.value))")
}
Second Solution:
You will add the sliderValue(value:) function but you will not create the parentView variable instead you will do as follow
#objc func onClose(){
if let viewController = presentingViewController as? ViewController {
viewController.sliderValue(value: focusTimeSlider.value)
}
self.dismiss(animated: true, completion: nil)
print("Focus Time : \(Int(focusTimeSlider.value))")
print("Short Break Time : \(Int(shortBreakTimeSlider.value))")
print("Long Break Time : \(Int(longBreakTimeSlider.value))")
}
self.presentingViewController this variable holds the presenting view controller which in this case will hold the value for the ViewController then you will need to downcast it to be able to access the sliderValue function . you can find more about this property in the apple documentation presentingViewController

Related

Save actions on previous ViewController

I have my main screen with only one button on it "Show next screen". When the second screen(VC) pops up it has 2 buttons (go back and toSelect button).
My goal is to when I show my second screen and select a button on it then go back to first. The button on my second screen will stay selected. How can I do that?
So basically I need to save my actions on the second screen so if I go back to it it will show everything I did.
What is the best way to do it?
Storyboard
The easiest way to achieve this using Delegate and protocol.
you should listen and save the changes of SecondViewController at FirstViewController using delegate methods.
And when you are presenting the secondViewController you will share the saved changes to secondViewController so that button can be selected on behalf of that information
Code -
class FirstViewController: UIViewController {
//secondViewController States
private var isButtonSelected = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func gotoSecondVCAction(_ sender: Any) {
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
guard let secondVC = storyBoard.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController else { return }
secondVC.isButtonSelected = isButtonSelected
secondVC.delegate = self
self.present(secondVC, animated: true, completion: nil)
}
}
extension FirstViewController: ButtonSelectionProtocol {
func button(isSelected: Bool) {
isButtonSelected = isSelected
}
}
and for secondViewController
protocol ButtonSelectionProtocol {
func button(isSelected:Bool)
}
class SecondViewController: UIViewController {
var isButtonSelected : Bool = false
var delegate:ButtonSelectionProtocol?
#IBOutlet weak var selectButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
if isButtonSelected {
selectButton.tintColor = .red
selectButton.setTitle("Selected", for: .normal)
}else{
selectButton.tintColor = .green
selectButton.setTitle("Select Me", for: .normal)
}
}
#IBAction func gobackAction(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
#IBAction func selectAction(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
isButtonSelected.toggle()
delegate?.button(isSelected: isButtonSelected)
}
}

How to hide pop up view on previous page when pressing back button on swift

I have this kind of flow page :
Setting Page --> Enter Password --> Go to Page X
So in setting page, in order to go to page X, I have to enter a password using pop up view.
When I'm in page X and i want to go back to previous page, I go to enter password pop up view, instead of the setting page.
How do I skip that page?
My pop up view code is something like this :
let btn = storyboard?.instantiateViewController(withIdentifier: "PopUpView") as! PopUpView
addChild(btn)
btn.view.frame = view.frame
view.addSubview(btn.view)
btn.didMove(toParent: self)
I'm fairly new here, any help will be appreciated.
Thankyou.
use the settings view controller's present function to open the popup.
//In your settings view
func openPopup() {
let btn = storyboard?.instantiateViewController(withIdentifier: "PopUpView") as! PopUpView
self.present(btn, animated: true, completion: nil)
}
When the user clicks ok, call dismiss on your popup view and use the closure to initiate the page opening to X
//In your 'PopUpView' On the OK button action of your popup
func didTouchOk() {
self.dismiss(animated: true) { [weak self] in
guard let self = self else { return }
//Put your open page X code here
let XView = storyboard?.instantiateViewController(withIdentifier: "XViewController") as! XView
self.present(XView, animated: true, completion: nil)
}
}
if you are using navigationController:
Declare a protocol in your PopUpView
protocol popupDelegate: class {
func userDidTouchOkInPopup()
}
create a weak var in your PopUpView
weak var delegate: popupDelegate? = nil
In your settings viewcontroller:
Assign delegate to popup before pushing
func openPopup() {
let btn = storyboard?.instantiateViewController(withIdentifier:
"PopUpView") as! PopUpView
btn.delegate = self
self.navigationController?.pushViewController(btn, animated: true)
}
Implement an extension for this protocol
extension SettingsViewController: popupDelegate {
func userDidTouchOkInPopup() {
self.navigationController?.popViewController(animated: true)
let XView = storyboard?.instantiateViewController(withIdentifier:
"XViewController") as! XView
self.navigationController?.pushViewController(XView, animated: true)
}
}
Modify the Ok action in your PopUpView
//In your 'PopUpView' On the OK button action of your popup
func didTouchOk() {
self.delegate?.userDidTouchOkInPopup()
}
If you are in navigationController hierarchy, use navigationController.popToViewController to go to the specific ViewController.
In ViewDidLoad, hide the present backButton and create a new One and associate action with it.
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.hidesBackButton = true
let newBackButton = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(backButtonFunction))
self.navigationItem.leftBarButtonItem = newBackButton
}
Inside backButtonFunction, you can put the code
#objc func backButtonFunction(){
if let navController = self.navigationController {
for controller in navController.viewControllers {
if controller is SettingsViewController { // Change name of ViewController accordingly
navController.popToViewController(controller, animated:true)
break
}
}
}
}

Show other array in next view controller depending on button pressed in previous

I spent hours to make this work but I am trying to show an array in a view controller based on the button that is pressed in the previous view. So I want to use the same view controller but with different data.
In the view controller:
#IBAction func firstDeck(_ sender: UIButton) {
var dataSource : CardsDataModel? {
didSet {
label.text = cardsDeck.FirstDate()
}
}
}
#IBAction func secondDeck(_ sender: UIButton) {
var dataSource : CardsDataModel? {
didSet {
label.text = cardsDeck.PizzaFriends()
}
}
}
So there are two cardDecks: PizzaFriends and FirstDates. I tried using IBAction from the buttons to then show the relevant cardsDeck but without success. The cards are empty.
Declare an Array of String type variable in NextViewController
var someData = [String]()
In viewDidLoad() method of NextViewController add this
print("Some Data: \(someData)")
In the PreviousViewController in the IBAction methods present/push the NextViewController with assign someText variable according to which button has been pressed
#IBAction func firstDeck(_ sender: UIButton) {
let vc = NextViewController()
vc.someData = cardsDeck.FirstDate()
// If you want to present NextViewController
present(vc, animated: true, completion: nil)
// If you want to push NextViewController to navigation stack
//navigationController?.pushViewController(vc, animated: true)
}
#IBAction func secondDeck(_ sender: UIButton) {
let vc = NextViewController()
vc.someData = cardsDeck.PizzaFriends()
// If you want to present NextViewController
present(vc, animated: true, completion: nil)
// If you want to push NextViewController to navigation stack
//navigationController?.pushViewController(vc, animated: true)
}
Here is a sample NextViewController
class NextViewController: UIViewController {
var someData = [String]()
var cardView = SwipeCardView(frame: CGRect(x: 10, y: 150, width: 300, height: 600))
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
self.view.addSubview(cardView)
cardView.label.text = "\(someData)"
}
}

How to pass the value from ViewController B to ViewController A during dismiss ViewController using Swift? [duplicate]

This question already has answers here:
Delegates in swift?
(15 answers)
Closed 3 years ago.
My scenario, I am trying to pass the value from ViewController B to ViewController A during dismiss the view controller. Here I used below code but I can’t able to get the value in ViewController A.
ViewController B
// protocol used for sending data back
protocol isAbleToReceiveData {
func pass(data: String) //data: string is an example parameter
}
// Making this a weak variable so that it won't create a strong reference cycle
var delegate: isAbleToReceiveData?
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(true)
self.delegate?.pass(data: "someData") //call the func in the previous vc
}
#IBAction func Click_action(_ sender: Any) {
self.dismiss(animated: false, completion: nil)
self.delegate?.pass(data: "someData")
}
ViewController A
class MyViewController: UIViewController, isAbleToReceiveData {
func pass(data: String) {
print("USER: \(data)")
}
}
// MARK: FromTouch Action
#objc func fromTouchTapped(_ sender: UITapGestureRecognizer) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "ViewControllerB")
viewController.modalTransitionStyle = .crossDissolve
let navController = UINavigationController(rootViewController: viewController)
present(navController, animated: true, completion: nil)
}
Everything is right you missed assign delegate in your ViewControllerA while present ViewControllerB.
if let VC_B = self.storyboard?.instantiateViewController(withIdentifier: "ViewControllerB") as? ViewControllerB{
VC_B.delegate = self
VC_B.modalTransitionStyle = .crossDissolve
self.present(VC_B, animated: true, completion: nil)
}
Note
let viewController =
self.storyboard?.instantiateViewController(withIdentifier:
"ViewControllerB") as? ViewControllerB
instad of
let viewController =
self.storyboard?.instantiateViewController(withIdentifier:
"ViewControllerB")
Your ViewController A looks ok, but seems you did not set ViewController B's delegate variable, do it once you launch ViewController B, like so:
viewControllerA.present(viewControllerB, animated: true)
viewControllerB.delegate = viewControllerA // notice this line
Since you are within the instance of viewControllerA, replace viewControllerA with self
full delegation example below
protocol IsAbleToReceiveData: class {
func pass(data: String) //data: string is an example parameter
}
class ViewControllerA: UIViewController, IsAbleToReceiveData {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: CGRect(x: 15, y: 100, width: 0, height: 0))
button.addTarget(self, action: #selector(launchAction), for: .touchUpInside)
button.setTitle("Launch ViewController B", for: .normal)
button.setTitleColor(.black, for: .normal)
button.sizeToFit()
self.view.addSubview(button)
}
#objc func launchAction() {
let viewController = ViewControllerB() // guard let viewController = self.storyboard?.instantiateViewController(withIdentifier: "ViewControllerB") as? ViewControllerB else { return }
viewController.delegate = self
self.present(viewController, animated: true)
}
func pass(data: String) {
print("Received Data: \(data)")
}
}
class ViewControllerB: UIViewController {
weak var delegate: IsAbleToReceiveData?
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
let button = UIButton(frame: CGRect(x: 15, y: 100, width: 0, height: 0))
button.addTarget(self, action: #selector(exitAction), for: .touchUpInside)
button.setTitle("Exit ViewController B", for: .normal)
button.setTitleColor(.black, for: .normal)
button.sizeToFit()
self.view.addSubview(button)
}
#objc func exitAction() {
self.delegate?.pass(data: "Hello World!")
self.dismiss(animated: true)
}
func pass(data: String) {
print("Received Data: \(data)")
}
}
First B should have a delegate variable that points to A. This means their must be a direct connection such as A is the parent of B.
Another easy solution if there is no direct connection between A and B is to use Notification Center. Where B generates an event and A Add observer to that event. You can follow this example: Using Notification Center In Swift

UIBarButton click to set flag value using Swift 4.2

My scenario, I am having Two UIBarButton with action method, Here, whenever I am clicking Done and Cancel button I am moving to another ViewController. Once user clicked the Done barbutton I need to set some flag value and validate it another ViewController for button clicked or not clicked.
My ViewController One
let barButtonItem = UIBarButtonItem(image: UIImage(named: "backImgs"),
style: .plain,
target: self,
action: #selector(menuButtonTapped))
self.navigationItem.rightBarButtonItem = barButtonItem
#objc fileprivate func menuButtonTapped() { // here I need to set flag value }
My ViewController Two
class ViewControllertwo: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//Here need to validate flag values to button clicked or not
}
}
I partially understand your question , in here you need to go with tag concept, for e.g
override func viewDidLoad() {
super.viewDidLoad()
let barButtonItem = UIBarButtonItem(image: UIImage(named: "backImgs"),
style: .plain,
target: self,
action: #selector(menuButtonTapped(_:)))
barButtonItem.tag = 20
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(menuButtonTapped(_:)))
cancelButton.tag = 10
self.navigationItem.rightBarButtonItem = barButtonItem
self.navigationItem.leftBarButtonItem = cancelButton
}
handle your target function is like
#objc fileprivate func menuButtonTapped(_ sender: UIBarButtonItem) {
// if you dont want the tag concept, use title property for check which button tapped //print("get Tapped button title == \(sender.title)")
//if sender.tag == 20{
// clicked for another VC button, add your segue code here
// }else{
// pressed cancel button
// }
let vcTwo = self.storyboard?.instantiateViewController(withIdentifier: "ViewControllertwo") as! ViewControllertwo
vcTwo.getSelectedTag = sender.tag
self.navigationController?.pushViewController(vcTwo, animated: true)
}
on your VC2 create the one global Int for get the tag where its comes from,
** ViewControllertwo**
class ViewControllertwo : UIViewController {
var getSelectedTag = 0
override func viewDidLoad() {
super.viewDidLoad()
if getSelectedTag == 20 {
//pressed menu Tapped
}
}
}
It's hard to tell from your question, but assuming you are presenting ViewControllerOne from ViewControllerTwo, you're going to want to use the delegate pattern for this. This is similar to the way you use table/collection views, and you are essentially telling ViewControllerTwo to be ViewControllerOne's delegate so that it can react to the buttons being pressed.
Start by creating a protocol that defines the messages that ViewControllerOne can send to its delegate:
protocol ViewControllerOneDelegate: AnyObject {
func viewControllerOneDidTapDone(_ viewController: ViewControllerOne)
func viewControllerOneDidTapCancel(_ viewController: ViewControllerOne)
}
Then extend ViewControllerTwo to implement your protocol:
extension ViewControllerTwo: ViewControllerOneDelegate {
func viewControllerOneDidTapDone(_ viewController: ViewControllerOne) {
// Set your flag or do whatever you need to do on 'Done'.
// Then dismiss viewController.
}
func viewControllerOneDidTapCancel(_ viewController: ViewControllerOne) {
// Dismiss viewController
}
}
In ViewControllerOne, keep the delegate as a weak property and call the delegate methods on button press:
class ViewControllerOne: UIViewController {
weak var delegate: ViewControllerOneDelegate?
#objc private func donePressed() {
delegate?.viewControllerOneDidTapDone(self)
}
#objc private func cancelPressed() {
delegate?.viewControllerOneDidTapCancel(self)
}
}
Lastly, somewhere in ViewControllerTwo, you need to set yourself as ViewControllerOne's delegate. This will likely be when creating ViewControllerOne:
class ViewControllerTwo: UIViewController {
...
private func presentViewControllerOne() {
let viewControllerOne = ViewControllerOne(nibName:nil, bundle: nil)
viewControllerOne.delegate = self
// Present or push viewControllerOne
}
...
}
As I understand your question the solution is -
ViewContorllerOne
class ViewControllerOne : UIViewController {
var isMenubuttonTapped : Bool = false
override func viewDidLoad() {
super.viewDidLoad()
self.actionToPushOnViewControllerTwo()
NotificationCenter.default.addObserver(self, selector: #selector(actioFire), name: NSNotification.Name.init("MenuButtonTapped"), object: nil)
}
//Call from any where in viewControllerOne
func actionToPushOnViewControllerTwo() {
let viewControllerTwo : ViewControllerTwo = self.storyboard?.instantiateViewController(withIdentifier: "ViewControllerTwo") as! ViewControllerTwo
self.present(viewControllerTwo, animated: true, completion: nil)
}
#objc func actioFire(_ notification: Notification) {
print(notification.userInfo!["isMenuButtonTapped"] as Any)
if let isMenuButtonTapped = notification.userInfo!["isMenuButtonTapped"] as? Bool {
self.isMenubuttonTapped = isMenuButtonTapped
}
}
}
ViewControllerTwo
class ViewControllerTwo : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let barButtonItem = UIBarButtonItem(image: UIImage(named: "backImgs"),
style: .plain,
target: self,
action: #selector(menuButtonTapped))
self.navigationItem.rightBarButtonItem = barButtonItem
}
#objc fileprivate func menuButtonTapped() {
// here I need to set flag value
self.dismiss(animated: true) {
NotificationCenter.default.post(name: Notification.Name("MenuButtonTapped"),
object: nil,
userInfo:["isMenuButtonTapped": true])
}
}
}
Another Easy Solution is
self.dismiss(animated: true) {
if let tabController = self.presentingViewController as? UITabBarController {
if let navController = tabController.selectedViewController as? UINavigationController {
if let secondTab = navController.viewControllers.first as? HomeViewController {
secondTab.tfData = "YES"
}
} else {
if let secondTab = tabController.selectedViewController as? HomeViewController {
secondTab.tfData = "YES"
}
}
}
}

Resources