Undo redo Operation - ios

I have used the following code for undo redo operation. I am changing the label's background color and my undo/redo operation is working fine but now i have added label's text color so whenever i change only background color or text color individually it works fine but if i change background color and text color both at a time then it will not work properly. what should i do? please help.!
#IBOutlet var myObject: UILabel!
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
myObject.backgroundColor = UIColor.yellow
}
func setMyObjectColor(_ color: UIColor) {
(undoManager?.prepare(withInvocationTarget: self) as AnyObject).setMyObjectColor(myObject.backgroundColor!)
myObject.backgroundColor = color
}
func setMyObjectTextColor(_ color: UIColor) {
(undoManager?.prepare(withInvocationTarget: self) as AnyObject).setMyObjectTextColor(myObject.textColor!)
myObject.textColor = color
}
#IBAction func changeColor(_ sender: Any){
setMyObjectColor(UIColor.blue)
}
#IBAction func changeTextColor(_ sender: Any){
setMyObjectTextColor(UIColor.white)
}
#IBAction func undo(_ sender: Any) {
undoManager?.undo()
}
#IBAction func redo(_ sender: Any) {
undoManager?.redo()
}}

#IBOutlet var myObject: UILabel!
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
myObject.backgroundColor = UIColor.yellow
}
func setMyObjectColor(_ Backcolor: UIColor) {
(undoManager?.prepare(withInvocationTarget: self) as AnyObject).setMyObjectColor(myObject.backgroundColor!)
myObject.backgroundColor = Backcolor
}
func setMyObjectTextColor(_ Textcolor: UIColor) {
(undoManager?.prepare(withInvocationTarget: self) as AnyObject).setMyObjectTextColor(myObject.textColor!)
myObject.textColor = Textcolor
}
func setMyObjectText(_ Text: String) {
(undoManager?.prepare(withInvocationTarget: self) as AnyObject).setMyObjectText((myObject.text! as AnyObject) as! String)
myObject.text = Text
}
#IBAction func changeColor(_ sender: Any){
setMyObjectColor(UIColor.blue)
}
#IBAction func changeTextColor(_ sender: Any){
setMyObjectTextColor(UIColor.white)
}
#IBAction func changeText(_ sender: Any) {
setMyObjectText("Khush")
}
#IBAction func undo(_ sender: Any) {
undoManager?.undo()
}
#IBAction func redo(_ sender: Any) {
undoManager?.redo()
}
Using this code my issue is solved.

Related

How to get UIButton name in swift5?

I am currently making a pin-code. I want to incorporate all the functions into one function, in order to integrate the button event function into one So I want to get the name of UIButton, but I don't know how.
#IBOutlet weak var oneButton: UIButton!
#IBOutlet weak var twoButton: UIButton!
...
var pinCodeNum : String! = ""
...
#IBAction func OneButton(_ sender: UIButton) {
pincodeLogic(sender)
}
func pincodeLogic(_ sender: UIButton) {
// I want get value is (example : 'oneButton' or 'twoButton' or 'threeButton' more )
}
As you can see from my code, I'm getting a 'sender' as a parameter I want to know the name of oneButton or twoButton using this parameter. How do I know?
My number button consists of a button and a label.
EDit
#IBAction func OneButton(_ sender: UIButton) {
pincodeLogic(sender)
}
func pincodeLogic(_ sender: UIButton) {
if let number = sender.currentTitle {
print(number)
}
}
I can't see the print log.
You can compare the sender with your button instances.
func pincodeLogic(_ sender: UIButton) {
switch sender {
case oneButton:
print("oneButton pressed")
case twoButton:
print("twoButton pressed")
default:
print("unknown button pressed")
}
}
To access the contents of the label present in the button using the sender, this is an example:
#IBAction func OneButton(_ sender: UIButton) {
print(sender.titleLabel?.text)
}
so you could do this:
#IBAction func OneButton(_ sender: UIButton) {
pincodeLogic(sender)
}
func pincodeLogic(_ sender: UIButton) {
if let number = sender.titleLabel?.text {
print(number)
}
}
I hope I've been there for you. Let me know.
if you want to access the button action to perform some specific task.Just put a tag with your each button and add the same target to all.
#IBAction func btnAction(_ sender: UIButton) {
switch sender.tag {
case 1:
print("oneButton pressed")
case 2:
print("twoButton pressed")
default:
print("unknown button pressed")
}
}
If you need just to print the button title the do the following.
#IBAction func btnAction(_ sender: UIButton) {
print(sender.titleLabel?.text! as! String)
}
#IBAction func btnClick(_ sender: UIButton{
print(sender.titleLabel!.text!)
}

Switch statement for UserDefaults (Swift-Xcode)

I would like to know how i could do a switch-case/any good statement for user defaults instead of using if-else because as you can see from my code, i'm using 3 if statements which is abit redundant and ugly.
The purpose of this view controller is for a "Pick a card" game, the user gets to pick 3 cards each time and if he/she selects a card, they will not be able to select that particular card again.
import UIKit
class ViewController: UIViewController {
#IBOutlet var buttona: UIButton!
#IBOutlet var buttonb: UIButton!
#IBOutlet var buttonc: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
if (UserDefaults.standard.integer(forKey: "dissapear") == 1)
{
buttona.setImage(UIImage(named: "wildcardbackingblack.png"), for: .normal)
buttona.isEnabled = false
}
if (UserDefaults.standard.integer(forKey: "dissapear2") == 1)
{
buttonb.setImage(UIImage(named: "wildcardbackingblack.png"), for: .normal)
buttonb.isEnabled = false
}
if (UserDefaults.standard.integer(forKey: "dissapear3") == 1)
{
buttonc.setImage(UIImage(named: "wildcardbackingblack.png"), for: .normal)
buttonc.isEnabled = false
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func Button1(_ sender: Any) {
UserDefaults.standard.set(1, forKey:"dissapear")
self.performSegue(withIdentifier: "show", sender: nil)
}
#IBAction func Button2(_ sender: Any) {
UserDefaults.standard.set(1, forKey:"dissapear2")
self.performSegue(withIdentifier: "show", sender: nil)
}
#IBAction func Button3(_ sender: Any) {
UserDefaults.standard.set(1, forKey:"dissapear3")
self.performSegue(withIdentifier: "show", sender: nil)
}
}
func updateCard(button: UIButton, image: String, isEnabled: Bool) {
DispatchQueue.main.asyc {
button.setImage(UIImage(named:image), for: .normal)
button.isEnabled = isEnabled
}
}
.
.
.
let option : Int = UserDefaults.standard.integer(forKey: "dissapear")
switch (option) {
case 1:
self.updateCard(button: ..., image:"wildcardbackingblack.png", isEnabled: false)
case 2:
self.updateCard(button: ..., image:"wildcardbackingblack.png", isEnabled: false)
case 3:
self.updateCard(button: ..., image:"wildcardbackingblack.png", isEnabled: false)
default:
self.updateCard(button: ..., image:"default.png", isEnabled: false)
}
//Save the different integer value in same key user defaults.
#IBAction func Button1(_ sender: Any) {
UserDefaults.standard.set(1, forKey:"dissapear")
self.performSegue(withIdentifier: "show", sender: nil)
}
#IBAction func Button2(_ sender: Any) {
UserDefaults.standard.set(2, forKey:"dissapear")
self.performSegue(withIdentifier: "show", sender: nil)
}
#IBAction func Button3(_ sender: Any) {
UserDefaults.standard.set(3, forKey:"dissapear")
self.performSegue(withIdentifier: "show", sender: nil)
}
Here is how I would write this code, if I were sticking to the same UserDefaults storage. Note: you need to reconnect cardPressed(_:) to every button/card
import UIKit
class ViewController: UIViewController {
#IBOutlet var buttonA: UIButton!
#IBOutlet var buttonB: UIButton!
#IBOutlet var buttonC: UIButton!
let buttonKeyPairs: [(button: UIButton, key: String)] = [
(buttonA, "dissapear"),
(buttonB, "dissapear2"),
(buttonC, "dissapear3"),
]
override func viewDidLoad() {
super.viewDidLoad()
for (button, key) in buttonKeyPairs
where UserDefaults.standard.integer(forKey: key) == 1 {
button.setImage(UIImage(named: "wildcardbackingblack.png"), for: .normal)
button.isEnabled = false
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func buttonPressed(_ sender: UIButton) {
let key: String
switch UIButton {
case buttonA: key = "dissapear"
case buttonB: key = "dissapear2"
case buttonC: key = "dissapear3"
}
UserDefaults.standard.set(1, forKey: key)
self.performSegue(withIdentifier: "show", sender: self)
}
}

Linking two UISegmentedControls

I'm currently trying to connect two UISegmentedControls where the first Viewcontroller is connected to the second. Tapping the second UISegment will update the value of the first one.
ViewController:
class ViewController: UIViewController {
#IBOutlet weak var tipLabel: UILabel!
#IBOutlet weak var totalLabel: UILabel!
#IBOutlet weak var billField: UITextField!
#IBOutlet weak var tipController: UISegmentedControl!
#IBOutlet weak var splitController: UISegmentedControl!
#IBOutlet weak var splitLabel: UILabel!
let defaults = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
defaults.synchronize()
billField.becomeFirstResponder()
tipController.selectedSegmentIndex = defaults.integer(forKey: "default_tip_index")
print(tipController.selectedSegmentIndex)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// #IBAction func toSettings(_ sender: Any) {
// self.performSegue(withIdentifier: "toSettings", sender: self)
// }
#IBAction func onTap(_ sender: Any) {
view.endEditing(true)
}
#IBAction func calculateTip(_ sender: Any) {
let tipPercentages = [0.18, 0.20, 0.25]
let splitNumbers = [1,2,3,4]
let bill = Double(billField.text!) ?? 0
let tip = bill * tipPercentages[tipController.selectedSegmentIndex]
let total = bill + tip
tipLabel.text = String(format: "$%.2f", tip)
totalLabel.text = String(format: "$%.2f", total)
splitLabel.text = String(format: "$%.2f", total/Double((splitNumbers[splitController.selectedSegmentIndex])))
}
SettingViewController:
class SettingsViewController: UIViewController {
var tipPercentageIndex:Int!
#IBOutlet weak var settingsTipController: UISegmentedControl!
let defaults = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
settingsTipController.selectedSegmentIndex = defaults.integer(forKey: "default_tip_index")
// Do any additional setup after loading the view.
}
#IBAction func Index(_ sender: Any) {
tipPercentageIndex = settingsTipController.selectedSegmentIndex
}
#IBAction func saveButton(_ sender: Any) {
tipPercentageIndex = settingsTipController.selectedSegmentIndex
defaults.set(tipPercentageIndex, forKey: "default_tip_index")
defaults.synchronize()
self.performSegue(withIdentifier: "Tippy", sender: self)
}
#IBAction func Back(_ sender: Any) {
self.performSegue(withIdentifier: "Tippy2", sender: self)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
However, my solution does not update the value nor store the value when switching back from the second to the first.
Note: the first segues to the second.
Add an IBAction for Value Changed for the segmented controls, and update values for the affected controls:
func updateSegments(){
if let value = UserDefaults.standard.value(forKey: "key"){
let selectedIndex = value as! Int
yourSegmentedControl.selectedSegmentIndex = selectedIndex
} else {
yourSegmentedControl.selectedSegmentIndex = 0 // set to default
}
if let value = UserDefaults.standard.value(forKey: "anotherkey"){
let selectedIndex = value as! Int
anotherSegmentedControl.selectedSegmentIndex = selectedIndex
} else {
anotherSegmentedControl.selectedSegmentIndex = 0 // set to default
}
//etc...
}
#IBAction func yourSegmentedControlSelected(_ sender: UISegmentedControl) {
UserDefaults.standard.set(sender.selectedSegmentIndex, forKey: "key")
self.updateSegments()
}
#IBAction func anotherSegmentedControlSelected(_ sender: UISegmentedControl) {
UserDefaults.standard.set(sender.selectedSegmentIndex, forKey: "anotherkey")
self.updateSegments()
}
From how you've explained your code, I think your problem is that the code that loads your dependent values, is only called when your viewController is loaded. And I believe, the viewController you are "switching back" to, has already been loaded. So the set up code will not be executed again after updating your defaults.
One quick fix to try is moving your set up code for viewDidLoad to viewWillAppear:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
defaults.synchronize()
billField.becomeFirstResponder()
tipController.selectedSegmentIndex = defaults.integer(forKey: "default_tip_index")
print(tipController.selectedSegmentIndex)
}
Update
Just noticed you said the value is not stored, along with my pervious suggestion try this—
Create a method that sets the defaults to the settingsTipController.selectedSegmentIndex. When you load the SettingsViewController, add the method as a target to the settingsTipController that acts on a .valueChanged event.
When save is tapped the last selected value will be saved.
In SettingsViewController.swift:
override func viewDidLoad() {
super.viewDidLoad()
settingsTipController.selectedSegmentIndex = defaults.integer(forKey: "default_tip_index")
settingsTipController.addTarget(nil, action: #selector(didToggleSwitch), for: .valueChanged)
}
#objc func didToggleSwitch() {
tipPercentageIndex = settingsTipController.selectedSegmentIndex
defaults.set(tipPercentageIndex, forKey: "default_tip_index")
}
#IBAction func saveButton(_ sender: Any) {
tipPercentageIndex = settingsTipController.selectedSegmentIndex
defaults.set(tipPercentageIndex, forKey: "default_tip_index")
defaults.synchronize()
self.performSegue(withIdentifier: "Tippy", sender: self)
}

How do i set up a label so that when a button is pressed then it will change that value displayed on the label

How do i set up a label so that when a button is pressed then it will change that value displayed on the label and set it up that each time a button is pressed it they will all just add to the previous number that was pressed - and is it possible to set up 2 view scenes on the same view controller?
#IBOutlet weak var creditLabel: UILabel!
var savedNum:Int = "Credits: /0"
var Money : Int!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func oneDollar(_ sender: Any) {
let oneDollar = 1
}
#IBAction func fiveDollars(_ sender: Any) {
let fiveDollars = 5
}
#IBAction func tenDollars(_ sender: Any) {
let tenDollars = 10
}
#IBAction func twentyDollars(_ sender: Any) {
let twentyDollars = 20
}
#IBAction func fiftyDollars(_ sender: Any) {
let fiftyDollars = 50
}
#IBAction func oneHundredDollars(_ sender: Any) {
let oneHundredDollars = 110
}
}
I think what you're trying to do is something like this…
class ViewController: UIViewController {
#IBOutlet weak var creditLabel: UILabel!
var credit = 0 {
didSet {
creditLabel.text = "Credit: $\(credit)"
}
}
override func viewDidLoad() {
super.viewDidLoad()
credit = 0
}
#IBAction func oneDollar(_ sender: Any) {
credit += 1
}
#IBAction func fiveDollars(_ sender: Any) {
credit += 5
}
// etc
}
Is your Label connected to your UIViewController? What about the corresponding actions? Are you connecting the same actions to the same button? Need more information to help solve your error that's being thrown.

How to call for button action, inside from another button action in swift 3.0

I have below button action
#IBAction func actionB(_ sender: UIButton) {
print("something")
}
and I want to call above button action inside below button action.
#IBAction func actionC(_ sender: UIButton) {
//call to above button action in here
}
how can I do that. hope your help with this
Try this :
#IBAction func actionC(sender: AnyObject) {
//call to above button action in here
actionB(sender: sender);
}
try this solution
actionB("")
if you want you can also do like this
actionB(sender)
or
actionB(ButtonB)
Just change your code to:
#IBAction func actionB(sender: AnyObject?) {
print("something")
actionC(nil)
}
#IBAction func actionC(sender: AnyObject?) {
//call to above button action in here
}
Notice the optional mark after AnyObject.
or
#IBAction func actionB(sender: AnyObject) {
print("something")
}
#IBAction func actionC(sender: AnyObject) {
//call to above button action in here
actionB("" as AnyObject)
}
Here is the way to do it ...
#objc fileprivate func methodA(_ sender: UIButton) {
print("method A")
}
#objc fileprivate func methodB(_ sender: UIButton) {
methodA(sender)
}

Resources