Tap To Play Button Flashing Stops - ios

I have a game, and for the homepage, I want the “Tap To Play” button to fade in and out. This is my code:
import UIKit
class HomePageViewController: UIViewController {
#IBOutlet weak var highscoreLabel: UILabel!
#IBOutlet weak var taptoplay: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
flashing(buttonName: taptoplay)
let highscore = UserDefaults.standard.integer(forKey: "highscore")
highscoreLabel.text = "Highscore: \(highscore)"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func flashing(buttonName:UIButton) {
UIView.animate(withDuration: 1, delay: 0, options: UIViewAnimationOptions.autoreverse, animations: {
buttonName.alpha = 1
buttonName.alpha = 0
}, completion: nil)
}
}
My problem is that the text flashes perfectly like how I want about two times, but then it just disappears, and I can’t even click on the button. In fact, I can’t click on the button even when it does flash correctly.
The button was working fine before I added this code, and it’s still all linked up properly. Thanks for your help.

When you animated your button, the last thing you did to it was set its alpha to 0. Somehow, you need to set the alpha back to 1 after your button is finished animating, or, change the order, and set the alpha to 0 first.
EDIT: In addition, the default setting for user interaction is nil, so you need to add another option: allowUserInteraction.
Hope this helps.

Related

Swift viewDidLoad() in second View Controller Scene not working

I'm a beginner at swift and Xcode, so this question may sound very simple.
I have two view controllers, connected by a segue. My first view controller scene runs code from the viewDidLoad() function, and then calls the .performSegue() function for the second view controller scene to get displayed.
But now, I want to run code in that new .swift file. viewDidLoad() doesn't seem to work, so how do I get around this problem? Where else could I put my code, or what function should it be in?
EDIT
// Show main menu
self.performSegue(withIdentifier: "MenuSegue", sender: self)
is how I am switching between view controllers. The buttons display, but anything I write in viewDidLoad() does not work
EDIT 2
My code for ViewController.swift:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var startScreen: UIStackView! // H2O start screen
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Display start screen for 2 seconds before fading out
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2, execute: {
// Fade out start screen
UIView.animate(withDuration: 1, animations: {self.startScreen.alpha = 0})
// Wait 1 second from when start screen starts to fade out
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1, execute: {
// Show main menu
self.performSegue(withIdentifier: "MenuSegue", sender: self)
})
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
And for MenuViewController.swift:
import UIKit
class MenuViewController: UIViewController {
#IBOutlet weak var playButton: UIButton! // Play button
#IBOutlet weak var settingsButton: UIButton! // Settings button
#IBOutlet weak var volumeButton: UIButton! // Volume button
#IBOutlet weak var volumeStack: UIStackView! // Volume stack
#IBOutlet weak var volumePercentage: UILabel! // Volume percentage
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
print("Hello")
// Slowly display everything
playButton.alpha = 0
settingsButton.alpha = 0
volumeButton.alpha = 0
volumeStack.alpha = 0
// Fade out start screen
UIView.animate(withDuration: 1, animations: {self.playButton.alpha = 1; self.settingsButton.alpha = 1; self.volumeButton.alpha = 1; self.volumeStack.alpha = 1})
print("Hi")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func settings(_ sender: UIButton) {
// If the settings are hidden
if volumeButton.alpha == 0 {
// Rotate settings button to open settings
UIView.animate(withDuration: 0.5, animations: {sender.transform = CGAffineTransform(rotationAngle: .pi * -0.999)})
// Show extended settings
UIView.animate(withDuration: 0.5, animations: {self.volumeButton.alpha = 1})
}
else {
// Rotate settings button back to normal
UIView.animate(withDuration: 0.5, animations: {sender.transform = CGAffineTransform(rotationAngle: 0.0)})
// Hide extended settings
UIView.animate(withDuration: 0.5, animations: {self.volumeButton.alpha = 0})
}
}
#IBAction func volumeSlider(_ sender: UISlider) {
// Get slider value rounded to nearest 5
let value = round(sender.value / 5) * 5
// Set the value to nearest 5
sender.value = value
// Show volume percentage
volumePercentage.text = "\(Int(value))%"
}
#IBAction func playButton(_ sender: UIButton) {
// Hide all settings
settingsButton.alpha = 0
volumeButton.alpha = 0
volumeStack.alpha = 0
// Hide play button
sender.alpha = 0
}
}
Add your animation code inside viewWillAppear() method.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//Add animation code here
}

Swift 3 - UIView does not always display its content

I have a UIViewController (Main Menu) that is displayed after my other UIViewController (Loading Screen) finishes downloading/syncing data from the web. My Main Menu is having problems as it doesn't always display all the UIButtons that are on the view when it shows up! There is an inconsistancy, 1 out of every 10 times the Main Menu loads, all the UIButtons will appear.
Here's how the view should look:
Here's how the view usually shows up:
I can put my finger where the UIButtons should be and move my finger away and they'll appear. I can also tap where they should be and my segues will still trigger, but the UIButtons dont just automatically show up. It looks like
I attempted to add a MainMenuView.setNeedsDisplay() to the ViewDidLoad function and it didn't help. I also created a test UIButton on the view that triggers a MainMenuView.setNeedsDisplay() command but the hidden UIButtons remain hidden.
If I leave the screen idle for 30 or so seconds, all the UIButtons will randomly appear without me having to manually make them appear.
The Main Menu view is normal and all UIButtons are visible if I segue to it from any part of the app aside from my Loading Screen.
Edit: Main Menu Code - (references are Strong)
import UIKit
import CoreData
class MainMenuViewController: UIViewController {
// MARK: References
#IBOutlet var btnGasManifolds: UIButton!
#IBOutlet var btnAirCompressors: UIButton!
#IBOutlet var btnVacuumPumps: UIButton!
#IBOutlet var btnUnitConversion: UIButton!
#IBOutlet var btnCFMCalculator: UIButton!
#IBOutlet var mainMenuView: UIView!
var userData = [NSManagedObject]()
// MARK: Functions
override func viewDidLoad() {
var name = String()
for duserData in userData {
name = duserData.value(forKey: "nameFull") as! String
}
print("Main Menu\n->\(name)")
backgroundSetup()
}
override func viewDidAppear(_ animated: Bool) {
mainMenuView.setNeedsDisplay()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func btnTest(_ sender: Any) {
mainMenuView.setNeedsDisplay()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any!) {
if segue.identifier == "settingsSegue" {
let destination = segue.destination as! SettingsViewController
destination.userData = userData
}
}
// Background Setup
func backgroundSetup() {
let background = UIImage(named: "Data Screens")
var imageView : UIImageView!
imageView = UIImageView(frame: view.bounds)
imageView.contentMode = UIViewContentMode.scaleAspectFill
imageView.clipsToBounds = true
imageView.image = background
imageView.center = view.center
view.addSubview(imageView)
self.view.sendSubview(toBack: imageView)
}
}
The code which creates and shows the buttons after fetching the data from server needs to run on Main UI thread. If the code is running the background thread it will not properly display the UI elements and will take some time or manual scroll before showing the controls.
Run the code on Dispatch main queue.
dispatch_async(dispatch_get_main_queue(),{
//do some work
})
OR
Override one of the methods from ViewWillLayoutSubviews and ViewDidLayoutSubviews accordingly and run your code in these methods.

Smooth and Accelerating ProgressView

I am playing with ProgressView. What I want to achieve is stopping at 33%, 66%, 100% checkpoints on button click. It's working okay if I use progressView.progress = 0.33, but it directly lands to the checkpoint. Instead, having it smooth and accelerating would look so nice.
I thought animateWithDuration would work but unfortunately it doesn't. After some reading, I found out that I can do something with NSTimer, but I couldn't achieve it.
var progressView: UIProgressView?
override func viewDidLoad()
{
super.viewDidLoad()
progressView = UIProgressView(progressViewStyle: UIProgressViewStyle.Default)
progressView?.center = self.view.center
progressView?.trackTintColor = UIColor.redColor()
progressView?.progressTintColor = UIColor.greenColor()
view.addSubview(progressView!)
progressView!.progress = 0.0
}
Using this answer, I achieved making it move once in every second, but how can I make it go smooth, slow in the beginning and accelerating, so looks nice.
using setProgress method and setting animation to true makes animation work.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var pb: UIProgressView!
#IBOutlet weak var btn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
pb.progress = 0.00
}
#IBAction func btnPress(sender: UIButton) {
UIView.animateWithDuration(3, animations: {
self.pb.setProgress((self.pb.progress + 0.33), animated: true)
}, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Simple button on second view controller crashing app/ Swift

I have a very simple app so far. Two view controllers. I've set up a new .swift file for the second view. On each view I have a button that when pressed, changes a label to say "Pressed". Pretty simple.
On the first view controller everything works as expected. However, on the second view controller the app crashes when I press the button. I've set up IBOutlets and actions for all appropriate parts.
Does anyone have any insight?
code:
import UIKit
class PlayViewController: UIViewController {
#IBOutlet weak var newCardButton: UIButton!
#IBOutlet weak var labelTest: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func newCardButtonPressed(sender: UIButton) {
self.labelTest.text = "Pressed"
}
}
Screenshot:
Screenshot after crash- http://i.imgur.com/CHt8kA5.png
I think you should change the sender part like this.
#IBAction func newCardButtonPressed(sender: AnyObject) {
self.labelText.text = "Pressed"
}
If your connections are not set properly your app also crash. Delete them and reconnect it.From Utilities/connections inspector.

When user presses in a textField, segue to a tableviewController and pass back the row content to the textField, in Swift

Okay, let me explain my set up. I have one textField, a UIButton and an array filled with 3 questions. The idea is the user must answer each question, and the next button, will pass them to the next question in the array.
I would like to segue from a textField to a tableviewController, and then select an item in the row, and it have it returned back to the textField, so the user can then press Next button and continue to the next question.
I have tried many different ways and had no luck (not necessarily had any errors, it just doesn't work) - Below is my code thats on my main VC. I have also added a tableViewController in my main.storyboard already.
Any Help is very much appreciated! Thanks
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var questionLabel: UILabel!
#IBOutlet var buttonLabel: UIButton!
#IBOutlet var myBackgroundView: UIImageView!
#IBOutlet var questionTextField: UITextField!
let questions = ["Where are you going?", "Which city?", "When do you go?"]
var currentQuestionIndex = 0
let placeholder = ["Country", "City", "Date"]
var currentPlaceholderIndex = 0
#IBAction func nextButton(sender: AnyObject) {
// Initial setup on button press
questionTextField.hidden = false
barImage.hidden = false
// Reset text field to have no text
questionTextField.text = ""
// Displays the questions in array and displays the placeholder text in the textfield
if currentQuestionIndex <= questions.count && currentPlaceholderIndex <= placeholder.count {
questionLabel.text = questions[currentQuestionIndex]
questionTextField.placeholder = placeholder[currentPlaceholderIndex]
currentQuestionIndex++
currentPlaceholderIndex++
buttonLabel.setTitle("Next", forState: UIControlState.Normal)
// Animate text for questionLabel
UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.5, options: nil, animations: {
self.questionLabel.center = CGPoint(x: -110 , y: 305 + 20)
}, completion: nil)
} else {
performSegueWithIdentifier("countdownSegue", sender: self)
//Add some logic here to run whenever the user has answered all the questions.
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Hides the text field
questionTextField.hidden = true
questionTextField.delegate = self
// Sets the button text
buttonLabel.setTitle("Get started", forState: UIControlState.Normal)
// Sets the question text to be blank
questionLabel.text = ""
// Sets placeholder text in the text field
questionTextField.placeholder = ""
}
// resigns the keyboard when user presses the return/next key on keyboard
func textFieldShouldReturn(textField: UITextField) -> Bool {
questionTextField.resignFirstResponder()
return true
}
// Resigns the keyboard if the user presses anywhere on the screen
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
self.view.endEditing(true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
To do what you want you would need to implement the function textFieldDidBeginEditing from the delegate UITextFieldDelegate and call prepareForSegue form there
extension YourClass: UITextFieldDelegate
{
func textFieldDidBeginEditing(textField: UITextField)
{
performSegueWithIdentifier("yourSegue", sender: self)
}
}
Now you need a delegate to return the value select in the table view to the view that call it.
When you say "It is just not working" I am not sure in what part you are have a problem, anyway this should solve the problem of the view transition when the user click in the text field
To pass values from the detail view to the master view you will need to implement protocols. In detail view declare a protocol, my example is a login checking that happened in the detail view and the result is passed back:
protocol LoginDelegate
{
func loginResult(result: Bool)
}
Declare a optional delegate as a global in the same control:
var loginDelegate:LoginDelegate? = nil
Now test if this delegate exist before unwrap it and if it does call the function declare in the protocol:
if let loginDel = self.loginDelegate{
loginDel.loginResult(userResult)
}
this will help us to pass the value to the main view.
Back to the main view you will need to declare that the main view implement the new delegate method we create using:
extension MainViewController: LoginDelegate{
}
ans in viewDidLoad declare this view controler as a delegate from the login class
login.loginDelegate = self
No we just need to implement the function that will get called by the detail view controller with the boolean value:
extension LoginViewController: LoginDelegate
{
func loginResult(result: Bool)
{
//Save the result value to be used by the MainViewController
}
}
I know it is not a very simple process both after use it few times it will be easier to use and understand, it always a good idea read more in the documentation here

Resources