I'm making timer application and I have countdown slider.
I want to get current position of slider when I pause it.
I tried to use Int(value.sender) but I have this error message:
sliderOutlet.setValue(seconds, animated: true)
Cannot invoke 'setValue' with an argument list of type '(Int, animated: Bool)'
#IBOutlet weak var sliderOutlet: UISlider!
#IBAction func slider(_ sender: UISlider)
{
seconds = Int(sender.value)
timeScreen.text = timeString(time: TimeInterval(seconds))
}
#IBAction func startButton(_ sender: UIButton)
{
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(CountdownViewController.counter), userInfo: nil, repeats: true)
sliderOutlet.isHidden = true
}
#IBAction func pauseButton(_ sender: UIButton) {
stop()
timeScreen.text = timeString(time: TimeInterval(seconds))
sliderOutlet.setValue(seconds, animated: true)
}
func stop()
{
timer.invalidate()
sliderOutlet.isHidden = false
}
I expected when I tapped on pauseButton, sliderOutlet will show current seconds' position.
The setValue(_:animated:) method expects a Float, not an Int.
sliderOutlet.setValue(Float(seconds), animated: true)
Make sure the value of seconds is between the minimum and maximum values you have set for the slider which default to 0.0 and 1.0 respectively.
Related
The timer starts and countdowns while updating the title of the button when the view is loaded. I've called startTimer in viewDidLoad. This works fine as expected.
However, the problem I faced is when I call startTimer from the IBAction. I've verified the timer is working and the selector is being called. The button title doesn't change tho. What could be wrong in this case?
class ViewController: UIViewController {
#IBOutlet weak var button: UIButton?
var timer: Timer?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
startTimer()
}
func startTimer() {
countdownSeconds = 60
timer?.invalidate()
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
}
#objc func updateTimer() {
countdownSeconds -= 1
let countdown = countdownFormatter.string(from: TimeInterval(countdownSeconds))!
if countdownSeconds > 0 {
UIView.performWithoutAnimation {
button?.setTitle(countdown, for: .normal)
}
} else {
timer?.invalidate()
}
}
#IBAction func buttonTapped(_ sender: UIButton) {
startTimer()
}
}
I have a UISlider and AvAudioPlayer, currently I am able to set the UISlider to the currentTime of a AvAudioPlayer like so:
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: (#selector(RecordController.updateTimer)), userInfo: nil, repeats: true)
#objc func updateTimer() {
if(audio != nil) {
audioSlider.setValue(Float((self.audio?.currentTime)! / (self.audio?.duration)!), animated: false)
}
}
But how would I set the currentTime of the AVAudioPlayer when changing the value of the UISlider?
#IBAction func audioSliderUpdated(_ sender: Any) {
}
You can use the currentTime property of AVAudioPlayer:
#IBAction func audioSliderUpdated(_ sender: Any) {
if let slider = sender as? UISlider {
self.audio?.currentTime = slider.value
}
}
Use this, slider value changes according to time
#IBAction func slide(_ sender: UISlider) {
self.audio.currentTime = TimeInterval(slider.value)
}
You have to convert your slider value to a new value which based on your media file.
First, you must config your slider values to work in normalized values (from 0.0 to 1.0)
/// call this on viewDidLoad: configDefaults(for: audioSlider)
func configDefaults(for slider: UISlider)
slider.minimumValue = 0.0
slider.maximumValue = 1.0
}
Then you should calculate currentTime from audioSlider.value and duration then set it to the player.currentTime.
#IBAction func audioSliderUpdated(_ sender: Any) {
guard let slider = sender as? UISlider,
let player = audio else {
return
}
player.currentTime = Double(slider.value) * player.duration
}
I am making timer. I cannot figure out how to make start button tapped only once as it is starting to count. And at stop button timer.invalidate() does not work
#IBAction func start(_ sender: Any) {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(W1ViewController.counter), userInfo: nil, repeats: true)
}
#IBOutlet weak var stopOutlet: UIButton!
#IBAction func stop(_ sender: Any) {
seconds = 30
label.text = "\(seconds)"
timer.invalidate()
audioPlayer.stop()
}
Just disable the button
#IBAction func start(_ sender: Any) {
stopOutlet.isEnabled = false
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(W1ViewController.counter), userInfo: nil, repeats: true)
}
Then re-enable when needed:
stopOutlet.isEnabled = true
UIButton extends UIControl. UIControl provides this and alot more functionality to all controls.
this is i seting a timer function, the code like this:
#IBAction func start(_ sender: UIButton) {
Timer.scheduledTimer(timeInterval: 1,
target: self,
selector:#selector(ViewController.action),
userInfo: nil,
repeats: true)
}
#objc func action() {
hoursMinutesSeconds()
if stop == true{
start = false
timer.invalidate()
timer.invalidate()
time = 0
}
}
#IBAction func stop(_ sender: UIButton){
start = false
timer.invalidate()
timer.invalidate()
time = 0
}
but, when i click the stop func, this function not work. mean is the timer not stop. timer stil working…… why? thank you for your time!!
I think you didn't set timer value
timer = Timer.scheduledTimer(timeInterval: 1,
target: self,
selector:#selector(ViewController.action),
userInfo: nil,
repeats: true)
First you have to declare it as fileprivate as below:
fileprivate var timer = Timer()
#IBAction func start(_ sender: UIButton) {
self.timer = Timer.scheduledTimer(timeInterval: 4,
target: self,
selector: #selector(self.updateTimerForLocation),
userInfo: nil,
repeats: true)
}
#IBAction func stop(_ sender: UIButton) {
timer.invalidate()
}
Ensure that you are invalidating correct instance of Timer.
Like in start function, you didn't assign timer instance to any object, but in stop function,you are using timer vaiable to stop that timer.
Which means you try to invalidate a variable, which never instantiated.
Still try below function to stop timer, after assigning timer variable.
#IBAction func stop(_ sender: UIButton) {
start = false
timer.invalidate()
timer = nil
time = 0
}
Hope this work
you are confusing between variable stop and func stop.
also you dont need 2 parameter to manage stop/start status
--
for your question,
you should retain the timer variable to able to use it in other func
declare a global timer
var timer: Timer!
then
timer = Timer.scheduledTimer(timeInterval: 1,
target: self,
selector:#selector(ViewController.action),
userInfo: nil,
repeats: true)
now you can invalidate it anywhere
I'm trying to make a simple timer in iOS using Swift.
The program is working fine but whenever my START UIButton is pressed the function of timer starts and runs multiple time as much as the button is pressed.
I want to disable the START UIButton as soon as the timer function starts so that it does not run multiple times.
Please help me for the same.
This is my code of ViewController
import UIKit
class ViewController: UIViewController {
var time = 0.0
var timer = Timer()
#IBOutlet weak var lbl: UILabel!
#IBAction func start(_ sender: UIButton)
{
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(ViewController.action), userInfo: nil, repeats: true)
}
#IBAction func pause(_ sender: UIButton)
{
timer.invalidate()
}
#IBAction func reset(_ sender: UIButton)
{
timer.invalidate()
time = 0.0
lbl.text = ("0")
}
func action()
{
time += 0.1
lbl.text = String(time)
}
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.
}
}
To disable your button you can just set it's isUserInteractionEnabled property in start function:
#IBOutlet weak var startButton: UIButton!
#IBAction func start(_ sender: UIButton) {
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(ViewController.action), userInfo: nil, repeats: true)
startButton.isEnabled = false
}
Then set it back to true in pause and reset methods:
#IBAction func pause(_ sender: UIButton) {
timer.invalidate()
startButton.isEnabled = true
}
#IBAction func reset(_ sender: UIButton) {
timer.invalidate()
startButton.isEnabled = true
//the rest of your code
}
The most reliable way to ensure that the timer is only started and stopped once is writing two methods which check the current state (timer is not nil if it's currently running):
var timer : Timer?
func startTimer()
{
guard timer == nil else { return }
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(ViewController.action), userInfo: nil, repeats: true)
// disable start button
}
func stopTimer()
{
guard timer != nil else { return }
timer!.invalidate()
timer = nil
// enable start button
}
In the methods you can enable/disable the button(s) accordingly.