How to identify i come from which button - ios

These both button shows same ViewController.
ViewController1.swift
#objc func btnEdit()
{
print("Edit")
let editDeptt = self.storyboard?.instantiateViewController(withIdentifier: "Add Department") as! AddDepartmentVC
self.navigationController?.pushViewController(editDeptt, animated: true)
}
#IBAction func btnNewDeptt(_ sender: Any)
{
let addDepttVC = self.storyboard?.instantiateViewController(withIdentifier: "Add Department") as! AddDepartmentVC
self.navigationController?.pushViewController(addDepttVC, animated: true)
}
ViewController2.swift
override func viewDidLoad() {
super.viewDidLoad()
//How to identify i come from which button
}

Add a property to your AddApartmentVC called action and set it before you push the view controller.
First create an enum:
enum Action {
case edit, newDept, unknown
}
Then define this property in your AddApartmentVC:
var action = Action.unknown
Then in your buttons' actions, set the property to the desired value:
editDeptt.action = .edit
or
addDepttVC.action = .newDept
Finally, in viewDidLoad(), check the value:
override func viewDidLoad() {
super.viewDidLoad()
switch(action) {
case .edit:
// do something for edit
case .newDept
// create a new Dept
case .unknown
print("what am I doing here?")
}
}

Add an instance variable name identify in your AddDepartmentVC and pass set the value of the same from your current VC like this
let editDeptt = self.storyboard?.instantiateViewController(withIdentifier: "Add Department") as! AddDepartmentVC
editDeptt.identify = "button1"
Then you can push it and check the variable in AddDepartmentVC

In ViewController2.swift, declare one variable like this
class ViewController2: UIViewController{
let var originTag: Int = 0
}
override func viewDidLoad() {
super.viewDidLoad()
if originTag == 0
{
// come from button 1 - btnEdit
}
else
{
// come from button 2 - btnNewDeptt
}
}
In ViewController 1, set originTag like this.
#objc func btnEdit()
{
print("Edit")
let editDeptt = self.storyboard?.instantiateViewController(withIdentifier: "Add Department") as! AddDepartmentVC
editDeptt.originTag = 0
self.navigationController?.pushViewController(editDeptt, animated: true)
}
#IBAction func btnNewDeptt(_ sender: Any)
{
let addDepttVC = self.storyboard?.instantiateViewController(withIdentifier: "Add Department") as! AddDepartmentVC
addDepttVC.originTag = 1
self.navigationController?.pushViewController(addDepttVC, animated: true)
}

Simply assign a tag for button -
Button1.tag=1
Button2.tag=2
Then check your button -
func onClickButton(sender: UIButton){
switch(sender.tag){
case 101 :
print("I am from button 1")
default :
print("I am from button 2")
}
}

use following it's perfectly working for you.
Take one public variable above class like below in Viewcontroller1.Swift
public var btnComingFrom = "first"
#objc func btnEdit()
{
btnComingFrom = "first"
print("Edit")
let editDeptt =
self.storyboard?.instantiateViewController(withIdentifier: "Add Department")
as! AddDepartmentVC
self.navigationController?.pushViewController(editDeptt, animated: true)
}
#IBAction func btnNewDeptt(_ sender: Any)
{
btnComingFrom = "second"
let addDepttVC = self.storyboard?.instantiateViewController(withIdentifier: "Add Department") as! AddDepartmentVC
self.navigationController?.pushViewController(addDepttVC, animated: true)
}
ViewController2.swift
override func viewDidLoad()
{
super.viewDidLoad()
if btnComingFrom == "first"
{
print("you are coming from first button")
}
if btnComingFrom == "second"
{
print("you are coming from second button")
}
}

Related

How to assign different actions for same UIButton?

while click on the button for the first time, the title of the button will get changed from "Add to Cart" to "Go to Cart". And from the next click the button will navigate to the next screen (cart page) [just like flipkart].
here is my piece of code:
#IBAction func addToCartbtnTapped(_ sender: Any) {
if let info = detailInfo {
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
(sender as AnyObject).setTitle("Go to Cart", for: .normal)
let cart = self.storyboard?.instantiateViewController(withIdentifier: "CartViewController") as? CartViewController
self.navigationController?.pushViewController(cart!, animated: true)
}
}
I'm able to change the title of the button. But whenever I click on the button for nth number of time also, the product is getting added to the cart, screen is not navigating.
How to solve this issue?
Update..
override func viewDidLoad() {
super.viewDidLoad()
UserDefaults.standard.string(forKey: "btn")
}
#IBAction func addToCartbtnTapped(_ sender: Any) {
if !Clicked {
if let info = detailInfo {
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
addingTOCart.setTitle("Go to Cart", for: .normal)
UserDefaults.standard.set("Go to Cart", forKey: "btn")
print("Clicked")
Clicked = true
return
}
}
if Clicked {
print("Perform Action")
let cart = self.storyboard?.instantiateViewController(withIdentifier: "CartViewController") as? CartViewController
self.navigationController?.pushViewController(cart!, animated: true)
}
}
This is how I am trying to store the "Go to Cart" state. But not working.. please suggest!
Add this code to check cart is already added or not, If added change title according in your detail controller:
override func viewWillAppear(_ animated: Bool) {
if let info = detailInfo {
let buttonTItle = (self.checkCartData(cartInfo: info) ? "Go to Cart" : "Add to Cart")
addToCartButton.setTitle(buttonTItle, for: .normal)
}
}
Next, Check before adding to cart. If already added, will navigate to cart page else add new cart item(changing button title too).
#IBAction func addToCartbtnTapped(_ sender: Any) {
if let info = detailInfo {
if checkCartData(cartInfo: info) {
let cart = self.storyboard?.instantiateViewController(withIdentifier: "CartViewController") as? CartViewController
self.navigationController?.pushViewController(cart!, animated: true)
} else {
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
(sender as AnyObject).setTitle("Go to Cart", for: .normal)
}
}
}
Check Cart data here:
func checkCartData(cartInfo: jsonstruct) -> Bool {
guard let cart = self.getCartData() else { return false }
return (cart.contains(where: { $0.cartItems.name == cartInfo.name }) ? true : false )
}
Get all Cart Data with this method:
func getCartData() -> [CartStruct]? {
let defaults = UserDefaults.standard
var tempCart: [CartStruct]?
if let cdata = defaults.data(forKey: "cartt") {
tempCart = try! PropertyListDecoder().decode([CartStruct].self, from: cdata)
}
return tempCart
}
You can apply check on your button title for performing two different actions. Also you are showing alert and pushing View Controller at the same time which might be the reason for screen not navigating.
#IBAction func addToCartbtnTapped(_ sender: UIButton) {
if let info = detailInfo {
switch sender.currentTitle! {
case "Add to Cart":
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
(sender as AnyObject).setTitle("Go to Cart", for: .normal)
case "Go to Cart":
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
(sender as AnyObject).setTitle("Go to Cart", for: .normal)
default:
print("Default Case")
}
}
}
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var btn: UIButton!
var Clicked:Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func btnClick(_ sender: Any) {
if !Clicked {
btn.setTitle("Click", for: .normal)
print("Clicked")
Clicked = true
return
}
if Clicked {
print("Perform Action")
}
}
}

use popToRootViewController and pass Data

I'm applying for a junior developer position and I've got a very specific task, that already took me 3 days to complete. Sounds easy - pass data to rootViewController.
That's what I've done:
1)
private func userDefaultsToRootController() {
let input = textField.text!
defaults.set(input, forKey: "SavedLabel")
navigationController?.popViewController(animated: true)
}
private func segueToRootViewController() {
let destinationVC = MainScreen1()
let input = textField.text!
if input == "" { self.navigationController?.popToRootViewController(animated: true) }
destinationVC.input = input
navigationController?.pushViewController(destinationVC, animated: true)
}
private func popToNavigationController() {
let input = textField.text!
if let rootVC = navigationController?.viewControllers.first as? MainScreen1 {
rootVC.input = input
}
navigationController?.popToRootViewController(animated: true)
}
I've used CoreData
But here is the difficult part - I've got an email, that all these methods are not good enough and I need to use delegate and closure. I've done delegation and closures before, but when I popToRootViewController delegate method passes nil. Could you at least point where to find info about this?
** ADDED **
There are 2 View Controllers: Initial and Second one.
That's what I have in the Initial View Controller:
var secondVC = MainScreen2()
override func viewDidLoad() {
super.viewDidLoad()
secondVC.delegate = self
}
That's how I push SecondViewController
#objc private func buttonTapped(_ sender: CustomButton) {
let nextViewController = MainScreen2()
navigationController?.pushViewController(nextViewController, animated: true)
}
In SecondViewController I've got this protocol
protocol PassData {
func transferData(text: String)
}
Also a delegate:
var delegate: PassData?
This is how I go back to initial view controller
#objc private func buttonTapped(_ sender: CustomButton) {
if let input = textField.text {
print(input)
self.delegate?.transferData(text: input)
self.navigationController?.popToRootViewController(animated: true)
}
}
Back to the Initial view controller where I've implemented delegate method
extension MainScreen1: PassData {
func transferData(text: String) {
print("delegate called")
label.text = text
}
}
Delegate doesn't get called.
BASED ON YOUR EDIT:
You must set the delegate in buttonTapped
#objc private func buttonTapped(_ sender: CustomButton) {
let nextViewController = MainScreen2()
nextViewController.delegate = self // HERE WHERE YOU SET THE DELEGATE
navigationController?.pushViewController(nextViewController, animated: true)
}
You can delete the second instance and your code in viewDidLoad. That's not the instance you push.
This should point you in the right direction to use delegation and completion handler.
protocol YourDelegateName {
func passData(data:YourDataType)
}
class SecondViewController: UIViewController {
var delegate: YourDelegateName?
func passDataFromSecondViewController(){
YourCoreDataClass.shared.getCoreData { (yourStringsArray) in
self.delegate?.passData(data: yourStringsArray)
self.navigationController?.popToRootViewController(animated: true)
}
}
class InitialViewController: UIViewController, YourDelegateName {
override func viewDidLoad() {
super.viewDidLoad()
// or whenever you instantiate your SecondViewController
let secondViewController = SecondViewController()
secondViewController.delegate = self //VERY IMPORTANT, MANY MISS THIS
self.navigationController?.pushViewController(createVC, animated: true)
}
func passData(data:YourDataType){
//user your data
}
}
class YourCoreDataClass: NSObject {
static let shared = YourCoreDataClass()
func getCoreData (completion: ([String]) -> ()){
........... your code
let yourStringsArray = [String]() // let's use as example an array of strings
//when you got the data your want to pass
completion(yourStringsArray)
}
}

Refresh Storyboard viewcontroller using swift iOS

Im having button in all viewcontrollers to change language
LanguageViewController.swift
class LanguageViewController: UIViewController {
#IBAction func actionChange(_ sender: Any) {
L102Language.currentAppleLanguage()
L102Language.setAppleLAnguageTo(lang: "en")
// below code to refresh storyboard
self.viewDidLoad()
}
}
L102Language.swift
class func currentAppleLanguage() -> String{
let userdef = UserDefaults.standard
let langArray = userdef.object(forKey: APPLE_LANGUAGE_KEY) as! NSArray
let current = langArray.firstObject as! String
let endIndex = current.startIndex
let currentWithoutLocale = current.substring(to: current.index(endIndex, offsetBy: 2))
return currentWithoutLocale
}
/// set #lang to be the first in Applelanguages list
class func setAppleLAnguageTo(lang: String) {
let userdef = UserDefaults.standard
userdef.set([lang,currentAppleLanguage()], forKey: APPLE_LANGUAGE_KEY)
userdef.synchronize()
}
I inherited LanguageViewController in all my FirstViewCOntroller, SecondController as below
class FirstViewController: LanguageViewController {
}
class SecondController: LanguageViewController {
}
If I call self.viewDidLoad() it fails to change language from view defined in storyboard. How to reload storyboard, so that the language should change in all viewcontroller,if any button from any viewcontroller is clicked? Thanks!
You can use NotificationCenter for reloading the view controllers content, this will also reload the content of view controllers that are not visible.
extension Notification.Name {
static let didChangeLanguage = Notification.Name("didChangeLanguage")
}
override func viewDidLoad() {
//Add a listener
NotificationCenter.default.addObserver(self, selector: #selector(onDidChangeLanguage(_:)), name: .didChangeLanguage, object: nil)
}
#IBAction func actionChange(_ sender: Any) {
L102Language.currentAppleLanguage()
L102Language.setAppleLAnguageTo(lang: "en")
// Notify about the change.
NotificationCenter.default.post(name: .didChangeLanguage, object: self, userInfo: nil)
}
#objc func onDidChangeLanguage(_ notification:Notification) {
// reload content using selected language.
}
Correct me if I'm wrong. but I think you don't need to reload all view controllers. you just need to update them when they get displayed, view controllers are behind the presented one are not visible for the user.
for doing that you can do something like this:
var currentLanguage = ""
override func viewDidLoad() {
currentLanguage = currentAppleLanguage()
loadContentForLanguage(currentLanguage)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// this will be executed every time this sceen gets display
if currentLanguage != currentAppleLanguage() {
currentLanguage = currentAppleLanguage()
loadContentForLanguage(currentLanguage)
}
}
func loadContentForLanguage(_ currentLanguage: String) {
//here it goes whatever you currently have in viewDidLoad
}
My apologies if this does not compile, my swift is really rusty.

TextField unloads value when navigating in Swift

I have two ViewControllers, each with one TextField to get user input number and two buttons to calculate and navigate.
The instance of TextField in the SecondVC is created by user when filling the TextFields and it exists and it is shown in the View
The problem is: when you leave the SecondView Controller after creating the object - Cell and you come back to it later, it is set back to cero, which is not the instance - Cell value
class MainViewController: UIViewController {
#IBOutlet weak var A3TextField: UITextField!
#IBAction func calc(_ sender: Any) {
let A3 = Cell(name: "A3", sheet: "", value: Double(A3TextField.text!)!)
print(A3)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
class SecondViewController: UIViewController {
#IBOutlet weak var B3TextField: UITextField!
#IBAction func calc2(_ sender: Any) {
let B3 = Cell(name: "B3", sheet: "", value: Double(B3TextField.text!)!)
print(B3)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
struct Cell {
var name: String = ""
var sheet: String = ""
var value: Double = 0
init(name: String, sheet: String, value: Double) {
self.name = name
self.sheet = sheet
self.value = value
}
}
When controller pop or push ,their temporary property value or object can not be save to other controller,even in itself controller ,when push and back ,their are the init value,if you want save value when page switching,suggest these solution:
1. Pass throw the attribute values(one => two)
OneViewController:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let twoVC = storyboard.instantiateViewController(withIdentifier: "TwoViewControllerID") as! twoViewController
twoVC.myStr="Controller one to controller two!"
self.present(twoVC, animated: true, completion: nil)
TwoViewController
var myStr=String()
override func viewDidLoad() {
super.viewDidLoad()
print("get value:\(myStr)"
}
2, use NSUerDfault to save and get
SetValue:
let userDefault = UserDefaults.standard
userDefault.set(name, forKey: "name")
userDefault.synchronize()
GetValue:
let userDefault = UserDefaults.standard
let name = userDefault.object(forKey: "name") as? String
3,storybord pass value(one => two)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let theSegue=segue.destination as! twoViewController theSegue.myStr="other pass way" }
4,deleagte pass value(two => one)
based don back to front page
TwoViewController:
//(1)create a delegate before class
protocol FTVCdelegte : NSObjectProtocol{
//define method
// one method
func change(title:String)
//two method
func ChangeColoer (Coloer:UIColor)
//three method
func ChangSucces(YON:Bool)
}
//(2)create delegate object。
var delegate_zsj:FTVCdelegte?
//(3)click back button
#IBAction func backBtnAction(_ sender: UIButton) {
delegate_zsj?.change(title: "main page")
delegate_zsj?.ChangeColoer(Coloer: UIColor.red)
delegate_zsj?.ChangSucces(YON: true)
self.navigationController?.popViewController(animated: true)
}
OneViewController
//(4)inherit delegate:
class SecondViewController: UIViewController,FTVCdelegte,ChangeBtnDelege{
...
//(5)imple delegate method
func change(title: String) { self.title = title }
func ChangeColoer(Coloer: UIColor) { self.view.backgroundColor = Coloer }
func ChangSucces(YON: Bool) { print(YON) }
//(6)when pop page use
#IBAction func tiaozhuanBtnAction(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let oneVC = storyboard.instantiateViewController(withIdentifier: "OneViewControllerID") as! oneViewController
oneVC.delegate_zsj = self
self.navigationController?.pushViewController(oneVC, animated: true)
}
5,block pass value(two => one)
based don back to front page
TwoViewController:
//(1)define a block method:
var bbchange:((_ title:String,_ myColor:UIColor)->Void)?
//(2)back to front page:
#IBAction func backBtnAction(_ sender: UIButton) {
bbchange?("document",UIColor.green)
self.navigationController?.popViewController(animated: true)
}
OneViewController
//(3)next page invoke block method
#IBAction func tiaozhuanBtnAction(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let threeVC = storyboard.instantiateViewController(withIdentifier: "twoViewControllerID") as! twoViewController
twoVC.bbchange=
{
( title:String,myColor:UIColor) in
self.title=title
self.view.backgroundColor=myColor
}
self.navigationController?.pushViewController(twoVC, animated: true)
}

Can't get the value of a var in another class

I'm trying to get the value of a String var from an another class, but when i'm using it on the new class, the value is empty.
I've got the MainViewController.swift class with :
var movieIDSelected = String()
#IBAction func tapPosterButton(_ sender: UIButton) {
switch sender.tag
{
case 101: movieIDSelected = theaterMovieID[0]
print(movieIDSelected) //The value isn't empty
break
}
}
And the second MovieViewController.swift class with :
var HomeView = ViewPop()
override func viewDidLoad() {
super.viewDidLoad()
let movieID = HomeView.movieIDSelected
print(movieID) //The value is empty
}
With your current code try this in MainVC
if let home = UIApplication.shared.keyWindow?.rootViewController as? ViewPop {
print("home exists ",home.movieIDSelected)
}
//
but you should have only 1 segue to the destinationVC and link it to the VC not a segue for every button , then implement prepareForSegue and fire performSegue inside the button action to make the segue
//
#IBAction func tapPosterButton(_ sender: UIButton) {
switch sender.tag
{
case 101: movieIDSelected = theaterMovieID[0]
print(movieIDSelected) //The value isn't empty
self.performSegue(withIdentifier: "goToNext", sender:1)
break
}
}
//
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let des = segue.destination as! MovieViewController
des.sendedValue = self.movieIDSelected
des.buttonNumber = sender as! Int
}
//
class MovieViewController : UIViewController {
var sendedValue = ""
var buttonNumber = 0 // default value won't affect
}

Resources