Connect 2 different buttons to the same outlet (Swift) - swift

I want to connect a second button to a label #IBOutlet var ourScore: UILabel! .
The first button is connected as
#IBAction func buttonPressed(sender: AnyObject) {
ourScore.text = "\(++score)"
}
How is it possible that I can add another button to the label, so when you click on the second button it works together. The first one counts it up and the second one needs to reset it, back to 0.

Your button isn't linked to your label outlet, the code of your IBAction makes reference to it. You posted this method:
#IBAction func buttonPressed(sender: AnyObject)
{
ourScore.text = "\(++score)"
}
so create a new method:
#IBAction func resetButtonPressed(sender: AnyObject)
{
score = 0;
ourScore.text = "\(score)"
}
Link that second IBAction method to your second button. Done.

You create the button in the same exact way you created the first one but instead of ++ it'd be -- (or whatever you want it to be).
The label is available to anything inside of your class so you can manipulate it and read from it anywhere.

Related

How to undo UITextField edits in Swift

I'm sure there's a simple answer to this, but I'm pretty noob to programming and have searched extensively here and on the few Undo tutorials I could find.
I have two buttons and a UITextField with a number in it. The buttons increment the number in the textfield up or down by 1 respectively. I have several more sets of these two buttons and a textfield, each representing something different. Then I have undo and redo buttons that undo the changes to the text fields caused by pressing the buttons. This all works great.
So now I'm trying to add the ability to undo changes from editing the text field directly with the number pad, so that it goes into the same undo stack and can be undone and redone from the same undo and redo buttons.
Here's a snippet of the code that controls the undo and redo of the button presses. Then, like I said, I have several more sets of these that all go into the same undo stack. Thanks.
The UITextField
#IBOutlet weak var Money: UITextField!
The Undo and Redo Buttons
#IBAction func Undo(_ sender: UIButton)
{
undoManager?.undo()
}
#IBAction func Redo(_ sender: UIButton)
{
undoManager?.redo()
}
The Up One and Down One Buttons
#IBAction func MonDown(_ sender: UIButton)
{
subtractOneMon(Mon: Money)
}
#IBAction func MonUp(_ sender: UIButton)
{
addOneMon(Mon: Money)
}
The Functions Registering the Undo/Redo
func subtractOneMon(Mon: UITextField)
{
undoManager?.registerUndo(withTarget: self, handler:
{(targetSelf) in
targetSelf.addOneMon(Mon: self.Money)
})
let Mon = Double(Money.text!)
let NewMon = Double(Mon! - 1)
Money.text = Int(NewMon).description
}
func addOneMon(Mon: UITextField)
{
undoManager?.registerUndo(withTarget: self, handler:
{(targetSelf) in
targetSelf.subtractOneMon(Mon: self.Money)
})
let Mon = Double(Money.text!) ?? 0
let NewMon = Double(Mon + 1)
Money.text = Int(NewMon).description
}
You might want to add an "Editing Changed" IBAction for your text field.
This function will be called each time any content of the field is changed.
You'd want to store the previous value of the text field somewhere.
Inside the "Editing Changed" IBAction you'd register an undo operation in your undoManager using the previous value and then update the previous value with the current value.
P.S. There's a potential memory leak in the way your handlers are implemented: currently they are holding a strong reference to your UIViewController. Consider adding [weak self] in the capture list. Check out the Memory Management article by John Sundell to learn more.

How to close/dismiss/hide a menu by clicking on a button in an embedded view from within it, in Swift?

I have created a menu app, using Swift, for Mac OS, within which, a custom view is the only menu item. There's a plus button on this custom view, which opens a window that has a textfield.
When I click on the plus button, the window appears, but the menu does not disappear. The textfield is also not focused. When I type one letter, the letter is not shown in the textfield, but the menu disappears, and the textfield is focused and ready to receive entry.
I want to have the custom view or menu disappear and have the textfield ready to receive keystrokes when I click on the plus button, not after I press an extra key.
How may I achieve that? What am I doing wrong?
Here's my code:
// CustomView.swift
var customWindow: CustomWindow!
override func awakeFromNib() {
customWindow = CustomWindow()
}
#IBAction func plusButtonClicked(_ sender: NSButton) {
customWindow.showWindow(nil)
}
// CustomWindow.swift
override var windowNibName : NSNib.Name? {
return NSNib.Name("CustomWindow")
}
override func windowDidLoad() {
super.windowDidLoad()
self.window?.center()
self.window?.makeKeyAndOrderFront(self)
self.window?.level = .mainMenu + 100
NSApp.activate(ignoringOtherApps: true)
if customTextField.acceptsFirstResponder {
customTextField.window?.makeFirstResponder(customTextField)
}
// CustomMenuContoller.swift
let statusBarItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
#IBOutlet weak var CustomMenu: NSMenu!
#IBOutlet weak var customView: CustomView!
var customMenuItem: NSMenuItem!
override func awakeFromNib() {
customMenuItem = CustomMenu.item(withTitle: "TheMenu")
customMenuItem.view = customView
statusBarItem.menu = CustomMenu
}
Inspired by El Tomato's comment, I found the solution.
Given the fact that the plusButtonClicked is limited to its own context, which is the controller within which it resides and all the public variables, I could not call a method on CustomMenu from it. Because CustomMenu in itself is not public. But its containing variable statusBarItem.menu, is public and accessible from all the other views. So I added statusBarItem.menu?.cancelTracking() to plusButtonClicked action and it works.

Changing content of UITextView by pressing button.

I'm new to swift programming, so this may be a dumb question, but how can I change the content of an UITextView Object by pressing a button.
The example I tested looks like this:
#IBOutlet weak var dataButton: UIButton!
#IBOutlet weak var dataView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func testButtonPressed(sender: UIButton) {
dataView.text = "Test worked."
}
Actually it doesn't work. My Storyboard has a ViewController from the Class where the above code is written. I also have the Button and the TextLabel. Do I need to specify anything in the Interface Builder or is something wrong with my code?
Thanks in advance for any help!!!
Make sure that your IBOutlet's and IBActions are connected in storyboard. It should work. You could set a breakpoint at the line with: dataView.text = "Test worked." to see if the code is reached. If it doesn't reach the breakpoint then your IBAction is not connected properly.
IBAction's sender parameter need an underscore before it, that is:
#IBAction func testButtonPressed(_ sender: UIButton) {
dataView.text = "Test worked."
}
are you sure you connected the code correctly?

How do you make a modal view appear outside of a controller?

I am trying to program a little game just to apply the concepts I learned in this course myself. When the game opens up, I would like for a custom modal view to tell the user how to play. Likewise, when they lose, I want to present a results page, which would be inside an if statement. I've searched all over the internet, and I can't find a way to display these views without an error. All that this video shows is how to show a display a view when a button is pressed; how do I display a custom modal view on command in code? (I am very new to Swift, so try to put it in layman's terms.) Thanks!
import UIKit
var numberValue = 0
let randomInt = getRandomNumber()
class ViewController: UIViewController {
#IBOutlet weak var buttonLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("HowToPlayView") as! HowToPlay
self.presentViewController(vc, animated: true, completion: nil)
// 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 buttonPressed() {
numberValue += 1
updateButtonValue(buttonLabel)
}
}
#IBAction func buttonPressed() {
numberValue += 1
updateButtonValue(buttonLabel)
}
}
That's my view controller. Getting error: Thread 1: EXC_BAD_ACCESS
My view in interface and connections
enter image description here
Ok, let's try a different approach to solve this issue. Above your ViewController you should see three different buttons like this:
Click on the first button and Ctrl + Drag to the view that you want to display and choose display modally. After that is done you should see this arrow appear:
This is called the segue from the first view to the second view and you can call this in your code to transition from one view to the next, but first we have to give our segue an identifier. You can do this by clicking on the arrow and a window should come up like this:
As you can see you will have to fill out the identifier field, and in my case I just named it "myAwesomeSegue".
Lastly, in the first ViewController run this code when you need to present the next view controller:
performSegueWithIdentifier("myAwesomeSegue", sender: nil)
Please note that if you use this method just delete the previous code you had before as this is a brand new approach (so basically delete this code):
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("HowToPlayView") as! HowToPlay
self.presentViewController(vc, animated: true, completion: nil)
Final code for the firstViewController:

Xcode v7.2 - New Radio Buttons: How to find selected

I am attempting to detect which Radio Button is currently selected using Xcode 7's new Radio Button template (NSButton).
I have created a simple action that will print to log the title of the sender when a radio button is selected. This does work:
#IBAction func radioButtonClicked(sender: AnyObject)
{
print(sender.selectedCell()!.title);
}
But what I am really looking for is the ability to know which radio button is selected elsewhere in my codes (specifically on an IBAction for a button click). I have tried:
#IBAction func uploadButtonPressed(sender: AnyObject)
{
print (radioButton.selectedCell()!.title);
}
This does compile and execute, the problem is it always gives me the title of the first radio button not the one that is actually selected.
Any ideas?
The "closest" I can get (which is not very clean, but works "kinda") is to see if radioButton.cell?state = 1. This tells me that the first radio button is selected. But this is a very poor way to code this and only allows for 2 radio button options.
if (radioButton.cell?.state == 1)
{
print ("Radio 1 Selected");
}
else
{
print ("Radio 2 Selected");
}
Use the identifier or tag property in Interface Builder to distinguish between radio buttons like:
#IBAction func selectOption(sender: AnyObject) {
let id:String = sender.identifier!!
case "first identifier":
// do some stuff
// ...
default:
// do default stuff
}
Another option would be a switch-case statement and defining outlets for each radio button like:
#IBOutlet weak var firstOption: NSButton!
#IBOutlet weak var secondOption: NSButton!
#IBOutlet weak var thirdOption: NSButton!
#IBAction func selectOption(sender: AnyObject) {
switch sender as! NSButton {
case firstOption:
print("firstOption")
case secondOption:
print("secondOption")
case thirdOption:
print("thirdOption")
default:
print("won't be called when exhaustive but must always be implemented")
}
}
I ended up finding a method for this.
First I setup a variable to store which item was checked (and pre-set the value to the value I want for the first radio button)
var databaseUploadMethod = "trickle-add";
Then I compare to see the title value of the selected item:
#IBAction func radioButtonClicked(sender: AnyObject)
{
if ((sender.selectedCell()!.title) == "Trickle Add")
{
databaseUploadMethod = "trickle-add";
}
else if ((sender.selectedCell()!.title) == "Bulk Add All Now")
{
databaseUploadMethod = "bulk-add";
}
}
For reference: I have two radio buttons, the first has a title of "Trickle Add" and the second is "Bulk Add All Now". Those are the values I am comparing in my if statement.