How can I click a button multiple times and repeat the function? - ios

I am new to app development and am starting by writing a 'Wheel of fortune' app in Xcode. I have a button and a wheel, and when I first launch the app I can click the button and the wheel will spin, however if I click the button again nothing happens and I have to restart the app, to click the button and make it spin. I have enclosed the code that I've used. I would appreciate if anyone take a look over my code and help me :)
The image of my code.
Here's my code in case you can't open the image.
import UIKit
import AudioToolbox
import AVFoundation
var count = 1
class ViewController: UIViewController {
#IBOutlet weak var Wheel: UIImageView!
#IBOutlet weak var Label: UILabel!
#IBAction func rotateButton(_ sender: Any) {
playSound (sound: "spinSound", type: "mp3")
var usedNumbers = [Int]()
let rotateButton = Int.random(in: 1...20)
Label.text = String(rotateButton)
if usedNumbers.contains (rotateButton) {
} else {
usedNumbers.append(rotateButton)
}
UIView.animate(withDuration: Double(rotateButton)) { () -> Void in
self.Wheel.transform = CGAffineTransform(rotationAngle: CGFloat(rotateButton))
}
UIView.animate(withDuration: Double(rotateButton), delay: Double(rotateButton)/2, options: UIView.AnimationOptions.curveEaseIn, animations: { () -> Void in
self.Wheel.transform = CGAffineTransform(rotationAngle: CGFloat(rotateButton))
}, completion: nil)
}
}

Related

How to properly call function (with IBOutlet variable in it) from another class in Swift 4

I can't figure out the proper way to call a function (with an IBOutlet variable inside of it) from another class. Basically after I click on the "Show Window" button, a custom alert view (container view) appears,
but when I click on the "Close" button, I want the alert view to disappear. Could someone please help me? Thanks, here's the code:
ViewController (main view):
import UIKit
class ViewController: UIViewController {
#IBOutlet var background: UIView!
#IBOutlet var windowView: UIView!
#IBAction func showWindowBtn(_ sender: Any) {
view.addSubview(windowView)
windowView.center = view.center
openAnimation()
}
// viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
background.alpha = 0
windowView.alpha = 0
}
// ---------- functions ----------- \\
// openAnimation
func openAnimation () {
UIView.animate(withDuration: 0.3) {
self.background.alpha = 1
self.windowView.alpha = 1
}
}
// closeAnimation
func closeAnimation () {
UIView.animate(withDuration: 0.3) {
self.background.alpha = 0
self.windowView.alpha = 0
}
}
}
ViewController 2 (alert view):
import UIKit
class ViewController2: UIViewController {
#IBAction func closeBtn(_ sender: Any) {
/*
In here, I want to access ViewController's 'closeAnimation()' function
without getting the 'unexpectedly found nil while unwraping an optional value'
error
*/
}
override func viewDidLoad() {
super.viewDidLoad()
// some code
}
}

Xcode button (IBAction) only working once

I'm new to iOS development. I'm trying to make a very simple application that rotates an image on a button press. The code works fine, but only once - i.e. the image rotates one time and then the button can no longer be pressed.
I've searched and found many similar issues, but nothing seems to fix my problem. Below is my ViewController.swift code.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var rotateImage: UIButton!
#IBAction func rotateImage(_ sender: Any) {
UIView.animate(withDuration: 2.0, animations: {
self.imageName.transform = CGAffineTransform(rotationAngle: (90.0 * .pi) / 90.0)
})
}
#IBOutlet weak var imageName: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
}
Ideally, the code should allow for multiple button presses, enabling the user to rotate the image as much as they would like.
It gets called multiple times, but it does the same rotation each time so nothing visually changes.
You can look into using a variable for your rotationAngle based on the image orientation so that it keeps rotating in your desired direction with each click.
An easy example takes your code and then uses a random value for the angle.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var imageName: UIImageView!
#IBAction func rotateImage(_ sender: Any) {
UIView.animate(withDuration: 2.0, animations: {
self.imageName.transform = CGAffineTransform(rotationAngle: (CGFloat.random(in: 0 ..< 360) * .pi) / 90.0)
})
}
}

Use animations to show color sequence (Swift)

Hi I'm new to Swift and I want to create a color memory game for IPhone where your app gives you a sequence of colors and you have to repeat it by pressing the right buttons. The sequence becomes longer and longer everytime you pressed the right buttons of the previous sequence.
I want the app to show which button is pressed by using an animation on the button. The sequence will make the buttons flash and then the user can recreate the sequence.
I have a method that does the flash(), which is a part of a class which is an extension of UIButton
func flash() {
let flash = CABasicAnimation(keyPath: "opacity")
flash.duration = 0.2
flash.fromValue = 1
flash.toValue = 0.1
flash.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
flash.autoreverses = true
flash.repeatCount = 1
layer.add(flash, forKey: nil)
}
When I perform this method on a sequence of buttons it flashes all of the buttons, written in the sequence, at the same time. This is not the way I want it of course, I want the buttons to flash one after another.
// ViewController.swift
import UIKit
import SpriteKit
class GameViewController: UIViewController {
var colorPattern = [Int]()
#IBOutlet weak var buttonGreen: UIButton!
#IBOutlet weak var buttonRed: UIButton!
#IBOutlet weak var buttonBlue: UIButton!
#IBOutlet weak var buttonYellow: UIButton!
var buttons = [UIButton]()
override func viewDidLoad() {
super.viewDidLoad()
buttons = [buttonGreen, buttonRed, buttonBlue, buttonYellow]
colorPattern = [0, 1, 2, 0, 1, 2]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func colorButtonTouched(_ sender: UIButton) {
print("button touched: ", sender.titleLabel!.text!)
//sender.flash()
doPattern()
}
func doPattern() {
UIView.animateKeyframes(withDuration: 1, delay: 0, options: [.calculationModeCubic], animations: {
// Add animations
for index in self.colorPattern{
print(index);
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 1, animations: self.buttons[index].flash)
}
}, completion:{ _ in
print("I'm done!")
})
}
}
When I perform this code button 1, 2 and 3 flash at the same time. Is there a way to fix this? or are animations just not the right way to go with looping sequences.
Try this
var currentButtonIndex = 0
func doPattern()
{
let currentButton = self.buttons[self.currentButtonIndex]
UIView.animateKeyframes(withDuration: 1, delay: 0, options: [.autoreverse], animations: {
currentButton.alpha = 0
}) { (complete) in
currentButton.alpha = 1
if self.currentButtonIndex == self.buttons.count - 1
{
self.currentButtonIndex = 0
return
}
self.currentButtonIndex += 1
self.doPattern()
}
}

Change the value of another class (Extension) with argument

A function whose argument is used for Extension of another class is described.
I want to change the value of the UIView property (alpha) that exists in that function "at the button tap in another class".
However, this function can be changed at ViewDidLoad time.
How can I change the value when tapping buttons?
If possible please write the code.
ViewController Class
class ViewController: UIViewController {
#IBOutlet weak var vHome: UICollectionView!
#IBOutlet weak var vSearch: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
selectRd(rd: 3) //This time can change calue of alpha.
}
}
extension ViewController {
func selectRd(rd reader:Int){
var animateView:UIView!
let animateVHome = vHome
let animateVSearch = vSearch
UIView.animate(withDuration: 0.3, delay: 0.0, animations: {
animateVHome.alpha = 0.0
animateVSearch.alpha = 0.0
}, completion: nil)
switch reader {
case 2:
animateView = animateVHome
case 3:
animateView = animateVSearch
default:
break
}
UIView.animate(withDuration: 0.3, delay: 0.3, animations: {
animateView.alpha = 1.0
}, completion: nil)
}
}
Another Class
class Another{
#objc func buttonTapped(sender : HeaderButton) {
let vC = ViewController
vC.selectRd(rd: 2) //This time can not!!
}
}
Please comment if you can not understand the question.
The problem is that you can't access a function of a class if its currently active , as this will result in a crash , so Add a var in viewControler
class ViewController: UIViewController {
#IBOutlet weak var vHome: UICollectionView!
#IBOutlet weak var vSearch: UICollectionView!
var index:Int?
override func viewDidLoad() {
super.viewDidLoad()
selectRd(rd: self.index) //This time can change calue of alpha.
}
}
..
class Another{
#objc func buttonTapped(sender : HeaderButton) {
let vC = ViewController
vC.index = 2 //This time can not!!
}
}

Weird Button Animation

It's my first try on IOS animation, so if I'm worry from the very beginning, just tell me the right direction.
All I want: when I click ButtonOne, Label disappears slowly.
The code as below:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var labelHeight: NSLayoutConstraint!
private var isHidden: Bool = false
#IBAction func clickButtonOne(sender: UIButton) {
isHidden = !isHidden
if isHidden {
labelHeight.constant = 0
} else {
labelHeight.constant = 60
}
UIView.animateWithDuration(1.0, animations: {
() -> Void in
self.view.layoutIfNeeded()
}, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Before I click ButtonOne:
After I click ButtonOne(label shrinks from bottom to top):
The UILabel is disappearing, but it's content is still visible.
You need to set the clipsToBounds property of the UILabel to true.
label.clipsToBounds = true
You can set the same property in the interface builder by checking the Clip Subviews property in the attributes inspector.
I think you should also animate UIView.alpha property:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var button: UIButton!
#IBOutlet weak var labelHeight: NSLayoutConstraint!
private var isHidden: Bool = false
#IBAction func clickButtonOne(sender: UIButton) {
isHidden = !isHidden
var alpha: CGFloat = 1
if isHidden {
alpha = 0
labelHeight.constant = 0
} else {
labelHeight.constant = 60
}
UIView.animateWithDuration(1.0, animations: {
() -> Void in
self.button.alpha = alpha
self.view.layoutIfNeeded()
}, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}

Resources