Pressing one UIButton triggers another UIButton: I don't want this to happen - ios

I am new to swift and xcode and am having a little trouble with creating this simple timer app with laps. When I press on the 'lap' button, the 'reset button is also triggered. Can anyone please help me with this? The buttons are right next to each other but I don't think this has anything to do with it. Additionally, I also commented out the entire body of the lap function and the same thing happened.
#IBAction func Reset(_ sender: Any)
{
min = 0
sec = 0
mil = 0
timer.invalidate()
createLabel()
var i = 0
while i < list.count
{
list[i].removeFromSuperview()
i = i + 1
}
running = false
}
#IBAction func Lap(_ sender: UIButton)
{
let word = UILabel()
list.append(word)
word.font = UIFont.systemFont(ofSize: 50)
word.text = make()
word.sizeToFit()
word.frame.origin = CGPoint(x:187.5,y:700)
self.Scroll.addSubview(word)
word.center = CGPoint(x:187,y:last)
last = last + 50
Scroll.contentSize.height = Scroll.contentSize.height + 50
}

It sounds like you wired up two #IBActions to your Lap button. Control-click on your Lap button in the Storyboard and delete the connection to Reset() by clicking on the x next to the action.
I'm guessing you copied the Reset button to make your Lap button. If the #IBAction is connected when you copy a button, you get that connection as well with the new button. So if you add a connection to the new button, it doesn't replace the previous action but instead becomes a second action.

I think you might have hooked up both buttons with same IBAction function. Make a print statement inside both IBAction functions and see what happens. Or, delete both IBAction functions (and referencing outlets from the storyboard) and re-connect. Also, check in the connection inspector (top right in storyboard) to see if you have any dead outlets.

Start debugging and you'll find the solution. Start from the first point. Like adding buttons in the storyboard and then connecting them to View Controller. I think you have connected one button to multiple actions.

Related

Swift - Updating UILabel Prevents Subviews from Changing

I'm currently learning Swift with Stanford's iOS 11 course. One of the projects is a card game called "Set". For that project I have a subview called "cardView" inside the ViewController, where all of the cards on the field are displayed.
Inside that "cardView" I create a subview for each card.
The goal is to find 3 cards that make up a "set".
I also have a hint button, which shows me a possible solution by changing the color of 3 cards that make up a "set".
Everytime I tap on that hint button though my score will decrease.
This is my IBAction:
#IBAction private func hintButtonPressed(_ sender: UIButton) {
for subview in cardView.subviews {
subview.layer.borderWidth = 0
}
game.hint()
if !game.selectedCards.isEmpty {
for index in game.indicesOfSelectedCards {
cardView.subviews[index].layer.borderWidth = 4
cardView.subviews[index].layer.cornerRadius = 8
cardView.subviews[index].layer.borderColor = UIColor.red.cgColor
print("cardView.subview[\(index)] changed borderColor.")
}
game.resetSelectedCards()
} else {
print("There are no sets on the field")
}
scoreLabel.text = "Score: \(game.score)"
}
For some reason if I change the text of the scoreLabel the subviews/cards that make up a "set" won't update and I can't see any change of the border. If I delete this line
scoreLabel.text = "Score: \(game.score)" though I can see the change of the subviews but then I don't see my updated score...
I also worked with breakpoints to figure out on which line this bug occurs and I found out that my subviews won't change as long as I have that line in there where I change the text of the scoreLabel even though that line is at the end of that method.
I just can't figure out how to update the score + show a possible solution at the same time.
Can anyone help me?

iOS: Why does hidden button still receive tap events?

According to the Apple docs, hidden UIButtons should not receive tap events.
However, our app has a UIButton receiving tap events despite being hidden.
This function is the IB Action invoked when the button is tapped. When the button is removed from Storyboard, this function doesn't get invoked. When the button is added to Storyboard, the function gets invoked -- even though the button is hidden.
To verify that the button is hidden, we put a breakpoint inside the function and ran expr sender.hidden from the Xcode debugger. The result: true.
The stack trace shows the IB Action is triggered by code in UIApplicationMain, not our code.
Through the Connections Inspector, we confirmed there is no other trigger for the IB Action except the mysterious button.
Thoroughly confused. Suggestions?
#IBAction func buttonTapped(sender: UIButton) {
// If here, handle tap
...
}
Try to set enable = false like this:
button.enabled = false
For Swift 3 would be:
button.isEnabled = false
The problem was an incomplete UIButton extension that didn't account for visibility in determining hit tests.
This function correctly handles the case where UIButtons are hidden.
extension UIButton {
public override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
// Ignore if button hidden
if self.hidden {
return nil
}
// If here, button visible so expand hit area
let hitSize = CGFloat(56.0)
let buttonSize = self.frame.size
let widthToAdd = (hitSize - buttonSize.width > 0) ? hitSize - buttonSize.width : 0
let heightToAdd = (hitSize - buttonSize.height > 0) ? hitSize - buttonSize.height : 0
let largerFrame = CGRect(x: 0-(widthToAdd/2), y: 0-(heightToAdd/2), width: buttonSize.width+widthToAdd, height: buttonSize.height+heightToAdd)
return (CGRectContainsPoint(largerFrame, point)) ? self : nil
}
}
A situation I encountered was that I was toggling between two different buttons based on application state. When I created the second of these two buttons, I copied and pasted the first. This also copied the first button's outlets.
I thought that the first button was being pressed when only the second button was showing, but in reality the second button was sending events to both the outlet I intended AND the one that was set when I copied the first button.
To determine if this is the case in your situation, go to the interface builder, select your button, and check that the touch events are set up exactly how you want in the connections inspector. If any of the connections are wrong, you can remove them by clicking the little 'x'.

I can't figure out how to set the correct button to be unhidden using swift

I'm trying to create a quiz app for a project, I'm having a problem when I try to set another button to be revealed when you select the correct answer. ex.
1+2=?
2
3
5
9
When they select 3, I want the continue button to appear to go to the next page.
#IBAction func Seaturtle(sender: UIButton) {
if sender.tag == 2 {
7.hidden = false
}
}
Go into your Storyboard and find the Continue button you wish to hide/unhide. Use Xcode's split screen view to have both your Storyboard and the associated code file open. Select the button, then Ctrl+Drag from the button into the code, creating an IBOutlet instead of an IBAction. Say you give it the name continueButton. Then, when you want to hide/unhide just call
continueButton.hidden = true
or
continueButton.hidden = false

Touch Up Inside not working properly

I have an app with some buttons, when those buttons are pressed the image on them should change. I assume that the TouchUpInside runs when you tap and remove the finger while still holding inside the area of the element, however it only works rarely and I'm not sure why.
The reason I use TouchUpInside instead of TouchDown is because I want the user to be able to cancel the action.
I'm sorry if I've misunderstood anything about those events and if this has already been asked. I couldn't find an answer to my problem searching the web.
//The IBAction is set to trigger on TouchUpInside
#IBAction func action11(sender: UIButton) {
setTile(sender)
}
func setTile(sender: UIButton) {
if turn {
print("O's turn")
sender.setImage(xTile, forState: .Normal)
turn = false
}
}
EDIT: Added the necessary code
There are some properties of UIButtons which you can use to achieve what you want.
You can use Default and selected state of uibutton to set two different images.
In XIB select state "Default" and assign default image to that state again select state to "Selected" and assign image which you want after button section.
and add following line in button selection method.
-(IBAction)buttonTapped:(UIButton *)sender{
sender.selected = !sender.selected;
}
Your understanding is correct, you need to use touchUpInside.
I assume you are trying to create a button that has a toggle function. On one touch you want the button to have the value Say "X" and when touched again the button has a value "O".
Take a look at this code below, this should do the job.
class ViewController: UIViewController {
var isButtonPressed = false{
// Adding a Property Observer, that reacts to changes in button state
didSet{
if isButtonPressed{
// Set the Value to X.
}else{
// Set the Value to O.
}
}
}
#IBAction func changeButtonValue(sender: UIButton) {
// Toggle the button value.
isButtonPressed = !isButtonPressed
}
}
If you don't set turn=true after the first time, this code is executed it will be executed only one.
if turn {
print("O's turn")
sender.setImage(xTile, forState: .Normal)
turn = false
}
Check if the button frame is large enough to get finger touch.
Apple says at least 35x35 pixel.

Is TouchUpOutside the correct control event for events outside of an element?

I'm three days new into swift development, even Xcode for that matter. I've created a UIView called EncounterMenu that appears over my app when i click the menu button. My goal is to have the EncounterMenu UIView close when I do anything outside of it.. This is what I have so far
override func viewDidLoad() {
super.viewDidLoad()
//create a button that spans the width & height of the encounter menu
let btnEncounterMenu = UIButton(type: UIButtonType.System) as UIButton
btnEncounterMenu.frame = CGRectMake(0, 0, EncounterMenu.frame.width, EncounterMenu.frame.height)
//(this is whats not working) If user clicks outside of button, call function "closeEncounter:"
btnEncounterMenu.addTarget(self, action: "closeEncounter:", forControlEvents: .TouchUpOutside)
//Add the button to the EncounterMenu
EncounterMenu.addSubview(btnEncounterMenu)
}
func closeEncounter(sender: UIButton!) {
EncounterMenu.hidden = true;
}
I tried changing it to TouchUpInside and it worked when i clicked inside the EncounterMenu UIView, so I figured it should be as easy as TouchUpOutside?
Any direction to what I'm doing wrong or how I can accomplish what I'm trying to do?
Touch up outside will not work because you need to be pressing on the menu first, then drag your finger outside for that to register. instead, the easiest option for you to do is to create a button that is the entire size of your view, and on that buttons touch down event, fire off close menu. just make sure that this big button is at the very back of the view, and everything else is built on top of it.

Resources