Toggle Play/Pause UIBarButtonItem in Toolbar using Swift - swift

I am trying to toggle my button between a play and pause image when I start and stop a ticker using Swift. My code:
import UIKit
class ViewController: UIViewController {
#IBOutlet var btnPlayPause: UIBarButtonItem!
var isPlaying = false
var timer = NSTimer()
var count = 0
#IBOutlet weak var lblTime: UILabel!
#IBOutlet var myToolbar: UIToolbar!
#IBAction func btnPlay(sender: UIBarButtonItem)
{
//set the button to animate
self.myToolbar.setItems([self.btnPlayPause], animated: true)
if !isPlaying //if the ticker is not ticking
{
//change the button to a pause button
println("worked")//start the ticker
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("updateTime"), userInfo: nil, repeats: true)
isPlaying = true
}else{ //if the ticker is ticking
//change the pause button to a play button
self.btnPlayPause = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: self, action: nil)
//pause the ticker
timer.invalidate()
//btnPlayPause.enabled = true
isPlaying = false
}
}
#IBAction func btnReset(sender: UIBarButtonItem)
{
//reset and restart the ticker
timer.invalidate()
count = 0
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("updateTime"), userInfo: nil, repeats: true)
}
#IBAction func btnStopit(sender: UIBarButtonItem)
{
//stop and reset the ticker to "0"
timer.invalidate()
count = 0
lblTime.text = String(count)
isPlaying = false
}
func updateTime()
{
//displays ticker label with count
lblTime.text = String(count++)
}
override func viewDidLoad()
{
super.viewDidLoad()
let button = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Pause, target: self, action: "btnStopit:")
self.btnPlayPause = button
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
}
The Play and all the other buttons on the toolbar are clearing and the toolbar is creating the Pause button alone by itself like this:
I want to just toggle my Play button with the Pause button without removing any of the other buttons from the toolbar. Is this possible?
If anyone could help me out with this I'd greatly appreciate it!
Thanks

Casting your button to a new instance of UIBarButtonItem isn't gonna do the needful. First create an outlet for your toolbar and retrieve the existing items, then change the play button item according to its position on the toolbar.
In my case the toggle button is on the left so I access it with index 0 and replace it with my corresponding toggle. And then calling the setItems() on your toolbar will update your toolbar. Set animation to true for a nice little fade animation.
#IBOutlet weak var toolBar: UIToolbar!
#IBAction func playPauseToggle(sender: UIBarButtonItem) {
var toggleBtn = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: self, action: "playPauseToggle:")
if playing {
player.pause()
playing = false
} else {
player.play()
toggleBtn = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Pause, target: self, action: "playPauseToggle:")
playing = true
}
var items = toolBar.items!
items[0] = toggleBtn
toolBar.setItems(items, animated: true)
}

slightly more dense version:
#IBAction func playPauseToggle(sender: UIBarButtonItem) {
var barButtonItems = toolBar.items!
barButtonItems[0] = UIBarButtonItem(barButtonSystemItem: player.rate == 1.0 ? .Pause : .Play,
target: self, action: "playPauseButtonWasPressed:")
toolBar.setItems(barButtonItems, animated: true)
}

//This code is tested and working with Swift 2
#IBOutlet weak var navigationBar: UINavigationBar!
//playToPause()
#IBAction func playButton(sender: UIBarButtonItem) {
let newBarButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Pause, target: self, action: "pauseButton:")
navigationBar.topItem?.rightBarButtonItem = newBarButton
}
// pauseToPlay()
#IBAction func pauseButton(sender: UIBarButtonItem){
let pauseBtnItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: self, action: "playButton:")
navigationBar.topItem!.rightBarButtonItem = pauseBtnItem
}

Related

Run Counter while button press

I am very new to swift and I want to make a button work like this:
Press the Button and hold. While the Button is pressed the label value goes up like every second +1 until the button is released.
This is what I get so far:
class ViewController: UIViewController {
var counter = 0;
override func viewDidLoad() {
super.viewDidLoad();
}
#IBOutlet weak var label: UILabel!
#IBAction func btn(_ sender: Any) {
if (sender as AnyObject).state != .ended{
counter+=1;
// wait 100ms
self.label.text = String (counter);
}
}
}
This is how I linked it:
You can achieve this using the UIButton actions Touch Down and Touch Up Inside
class ViewController: UIViewController {
var timer : Timer?
var startTime = 0
var timerReset = true // I don't know what logic you want. This basically has been added so the number is not set to 0 immediately when you release the button. You can also add another button to reset startTime variable and the label
#IBOutlet weak var numberLabel: UILabel!
#IBOutlet weak var numberButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
numberLabel.text = String(startTime) //initial value
// Do any additional setup after loading the view.
}
#IBAction func holdingTheButton(_ sender: Any) {
print("I am holding")
timerReset = false // reset to false since you are holding the button
guard timer == nil else { return }
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
}
#IBAction func buttonReleased(_ sender: Any) {
print("button released")
startTime = 0
timer?.invalidate()
timer = nil
timerReset = true // reset to true since you released.
}
#objc func updateTime(){
//update label every second
print("updating label ")
if timerReset {
startTime = 0
}
startTime += 1
numberLabel.text = String(startTime)
}
}
IMPORTANT: Make sure you are connecting in the right way. Touch Down has to be used if you want to call the function while you hold the button:
In your console, you should see this happening if you release the button after 10 SECONDS:
If you want to have a button to reset, you can just add the it and then connect it to the following function (but also make sure you remove the bool timeReset and the if statement inside updateTime:
#IBAction func resetTimer(_ sender: Any) {
startTime = 0
numberLabel.text = String(startTime)
}
You can achieve it using two sent event touch of UIButton and a Timer.
var counter = 0
var timer: Timer?
#IBAction func buttonTouchUpInside(_ sender: Any) {
timer?.invalidate()
print(counter)
}
#IBAction func buttonTouchDown(_ sender: Any) {
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(increaseCount), userInfo: nil, repeats: true)
}
#objc func increaseCount() {
counter += 1
print(counter)
}

UIBarButtonItem is not Highlighted after setting

I have declared two UIBarButtonItem, btnEdit and btnSave. initially i'm setting btnEdit in viewDidLoad. if user taps on btnEdit i want to set btnSave as rightBarButtonItem and when tapped on btnSave, set btnEdit
as rightBarButtonItem.
it is working fine and i'm able to tap on it but after first tap button is faded/ not in highlighted state. Images Attached.
How do i make it have normal State?
var btnEdit : UIBarButtonItem!
var btnSave : UIBarButtonItem!
#objc func btnEditTapped (){
textFieldViewNote.isEditable = true
navigationItem.rightBarButtonItem = btnSave
}
#objc func btnSaveTapped (){
textFieldViewNote.isEditable = false
navigationItem.rightBarButtonItem = btnEdit
}
override func viewDidLoad() {
super.viewDidLoad()
btnSave = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(btnSaveTapped))
btnEdit = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(btnEditTapped))
navigationItem.rightBarButtonItem = btnEdit
}
After loading VC - Edit in normal state
After tapping on edit - Save btn in normal State
Edit faded tapping on save barbutton
Below is the fixed code
class ViewController: UIViewController {
var btnEdit : UIBarButtonItem!
var btnSave : UIBarButtonItem!
#objc func btnEditTapped (){
btnSave = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(btnSaveTapped));
navigationItem.rightBarButtonItem = btnSave
}
#objc func btnSaveTapped (){
btnEdit = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(btnEditTapped)); navigationItem.rightBarButtonItem = btnEdit
}
override func viewDidLoad() {
super.viewDidLoad()
btnSave = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(btnSaveTapped))
btnEdit = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(btnEditTapped))
navigationItem.rightBarButtonItem = btnEdit
}
}

Auto refresh using swift

I know how to use pull to refresh and how to make a refresh button. I am just wondering if anyone knows how or can link me to a page that teaches me how auto refresh a page. Like every 15 seconds to automatically refresh.
Start with this:
#IBOutlet weak var yourButton: UIButton!
var timer: NSTimer!
var refresher: UIRefreshControl!
override func viewDidLoad() {
super.viewDidLoad()
yourButton.addTarget(self, action: "refresh:", forControlEvents: .TouchUpInside)
refresher = UIRefreshControl()
refresher.addTarget(self, action: "refresh:", forControlEvents: .ValueChanged)
timer = NSTimer.scheduledTimerWithTimeInterval(15.0, target: self, selector:"refreshEvery15Secs", userInfo: nil, repeats: true)
}
func refreshEvery15Secs(){
// refresh code
}
func refresh(sender: AnyObject){
refreshEvery15Secs() // calls when ever button is pressed
}
create NSTimer to fire every 15 seconds
let timer = NSTimer.scheduledTimerWithTimeInterval(15, target: self, selector: "refreshData:", userInfo: nil, repeats: true)
do the refresh in a callback function
func refreshData(timer: NSTimer){
refreshControl.beginRefreshing()
}

Swift - How to toggle between Play and Pause with UIBarButtonItem

I am trying with the below Swift code in my timer application to start and pause with the same button I have. But it is does not toggle. The button is set with Identifier as "Play" in the IDE. When I run the app, Timer starts and pauses correctly. But it does not toggle button. It always remain as "Play"
#IBAction func pressPausePlay(sender: AnyObject) {
if playPause == false
{
timer.invalidate()
self.playPauseButtonVar = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: self, action: "pressPausePlay")
playPause = true
}
else
{
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("updateTime"), userInfo: nil, repeats: true)
self.playPauseButtonVar = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Pause, target: self, action: "pressPausePlay")
playPause = false
}
}
You can use this Example scenarios to toggle between Play and Pause, for Button Titles, Image, Navigation Bar, ToolBar
import UIKit
import AVFoundation
class ViewController: UIViewController {
var myPlayer = AVAudioPlayer()
#IBOutlet var myNaviBar: UINavigationBar! //OUTLET TO NAVIGATION BAR IMPORTANT TO WORK WITH ITS BARBUTTON ITEMS
#IBOutlet var myToolBar: UIToolbar!
//**************START :Bottom LEFT TOOLBAR Bar Button Item***********/
#IBAction func toolBarItemPlay(sender: AnyObject) {
myToolBar.setItems([UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Pause, target: self, action: "toolBarItemPause:")], animated: true)
myPlayer.play()
}
#IBAction func toolBarItemPause(sender: AnyObject) {
myToolBar.setItems([UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: self, action: "toolBarItemPlay:")], animated: true)
myPlayer.pause()
}
//**************END :Bottom LEFT TOOLBAR Bar Button Item***********/
//**************START :Top LEFT Naivation Bar Button Item***********/
#IBAction func leftNavgationbarPlay(sender: UIBarButtonItem) {
myNaviBar.topItem?.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Pause, target: self, action: "leftNavigationbarPause:")
myPlayer.play()
}
//no need of control drag to this one below because we are calling from the above leftNavgationbarPlay's Selector/action
#IBAction func leftNavigationbarPause(sender : UIBarButtonItem) {
myNaviBar.topItem?.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Play, target: self, action: "leftNavgationbarPlay:")
myPlayer.pause()
}
//**************END :Top LEFT Naivation Bar Button Item***********/
//**************START :Top Right Naivation Bar Button Item***********/
#IBAction func naviPlay(sender: UIBarButtonItem) {
//change the topright navigation bar item from SystemItem Play '>' to systemitem pause '||'
// here I am assigning the top left item Play to Bar button item Pause
/* ACTION SELECTOR IMPORTANT. IT MUST CALL THE IB ACTION FUNCTION OF PAUSE AND VICEVERSA, WITH ":" */
myNaviBar.topItem?.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Pause, target: self, action: "naviPause:")
myPlayer.play()
}
#IBAction func naviPause(sender: UIBarButtonItem) {
myNaviBar.topItem?.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: self, action: "naviPlay:")
myPlayer.pause()
}
//**************END : Top Right Naivation Bar Button Item***********/
//************START :BUTTON IMAGE CHANGE - ">"to "||"************//
#IBAction func imagePlayButton(sender: UIButton) {
let chkImage = sender.currentImage!
if chkImage == UIImage(named: "play.png"){
sender.setImage(UIImage(named: "pause.png"), forState: .Normal)
myPlayer.play()
} else {
sender.setImage(UIImage(named: "play.png"), forState: .Normal)
myPlayer.pause()
}
}
//************END :BUTTON IMAGE CHANGE - ">"to "||"************//
//************START BUTTON TITLE CHANGE - PLAY to PAUSE************//
#IBAction func playButton(sender: UIButton) {
let chkTitle = sender.currentTitle
if chkTitle == "Play" {
sender.setTitle("Pause", forState: .Normal)
myPlayer.play()
} else {
sender.setTitle("Play", forState: .Normal)
myPlayer.pause()
}
}
//************END BUTTON TITLE CHANGE - PLAY to PAUSE************//
#IBAction func naviStop(sender: UIBarButtonItem) {
myPlayer.stop()
myPlayer.currentTime = 0
}
#IBOutlet var sliderUI: UISlider!
#IBAction func mySlider(sender: UISlider) {
myPlayer.volume = sliderUI.value
}
override func viewDidLoad() {
super.viewDidLoad()
let audioFilePath = NSBundle.mainBundle().pathForResource("ARRehman", ofType: "mp3")
//need NSURL from string
do {
myPlayer = try AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: audioFilePath!))
}
catch {
print("Some error")
}
}
}
You need to replace bar button items hold in UIToolbar after you assign a new instance to self.playPauseButtonVar.
If you have toolBar or navigationBar outlets:
self.toolBar.setItems([self.playPauseButtonVar], animated: true)
// Or
self.navigationBar.setItems([self.playPauseButtonVar], animated: true)
If your class inherits UIViewController:
self.setToolbarItems([self.playPauseButtonVar], animated: true)
// Or
self.navigationItem.setRightBarButtonItem(self.playPauseButtonVar, animated: true)
Yoichi, thanks for pointing me to the correct place. I removed the references on the Tool bar Outlet variable (bottomToolBar) under "Referencing Outlets". That resolved the error. However I am not able to add the tool bar outlet again, if I add, the error comes back!
it worked with me by creating bar button by code this is my code
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var navigationBar: UINavigationBar!
#IBOutlet weak var displayCountLabel: UILabel!
var buttonPause = UIBarButtonItem()
var buttonPlay = UIBarButtonItem()
var count=0
var timer=NSTimer()
override func viewDidLoad() {
super.viewDidLoad()
buttonPause = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Pause, target: self, action: "pauseAction")
buttonPlay = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: self, action: "playAction")
self.navigationBar?.topItem?.leftBarButtonItem = buttonPlay
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func stopTimer(sender: AnyObject) {
timer.invalidate()
count = 0
displayCountLabel.text = "\(count)"
self.navigationBar?.topItem?.leftBarButtonItem = buttonPlay
}
func pauseAction() {
self.navigationBar?.topItem?.leftBarButtonItem = buttonPlay
timer.invalidate()
}
func playAction() {
self.navigationBar?.topItem?.leftBarButtonItem = buttonPause
timer=NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("displayCount"), userInfo: nil, repeats: true)
}
func displayCount()
{
count++
displayCountLabel.text = "\(count)"
}
}

NSTimer() - timer.invalidate not working on a simple stopwatch?

I'm kind of at a wall of what to do, the program runs, but the timer.invalidate() does not work? Any tips are welcome.
I worked with this program in the past and worked through it and the timer.invalidate() worked flawlessly. I do not believe that it has to do with the fact that I put it into a function because before it wasn't working when I was just typing "timer.invalidate()" instead of "stop()"
Whenever I click the button Cancel on the iOS simulator it just resets it back to 0, but keeps counting.
Thanks in advance.
import UIKit
class ViewController: UIViewController {
var timer = NSTimer()
var count = 0
#IBOutlet weak var timeDisplay: UILabel!
#IBAction func playButton(sender: AnyObject) {
//play button
var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("result"), userInfo: nil, repeats: true)
}
#IBAction func resetTimer(sender: AnyObject) {
//cancel button
stop()
count = 0
timeDisplay.text = "0"
}
#IBAction func pauseButton(sender: AnyObject) {
stop()
}
func result() {
count++
timeDisplay.text = String(count)
}
func stop () {
timer.invalidate()
}
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.
}
}
In playButton() you are defining another timer, that can't be invalidated from outside this function - so by calling timer.invalidate() you invalidate just var timer = NSTimer() which doesn't carry any set timer in it.
So replace
var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("result"), userInfo: nil, repeats: true)
with
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("result"), userInfo: nil, repeats: true)