How to update a Status Item created by AppDelegate from NSViewController
I'm trying to create a Countdown Timer application that runs in the Menu Bar, with no window or dock icon. I've been building this off of mostly tutorials I find online and I know the code is kind of messy (I plan to clean up after it functions properly). The issue I'm running into. In the AppDelegate I create the StatusBar item with no issue, but I can't figure out how to update it from the viewController. It instead is creating a new StatusBar item.
//AppDelegate info
class AppDelegate: NSObject, NSApplicationDelegate
{
let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
let popover = NSPopover()
func applicationDidFinishLaunching(_ aNotification: Notification)
{
menuBarRefresh(self)
}
func menuBarRefresh(_ sender: Any?)
{
if let button = item.button
{
button.image = NSImage(named: NSImage.Name("2"))
//button.title = initialTime.stringValue
button.action = #selector(togglePopover(_:))
}
popover.contentViewController = TimerViewController.freshController()
}
@objc func togglePopover(_ sender: Any?)
{
if popover.isShown
{
closePopover(sender: sender)
}
else
{
showPopover(sender: sender)
}
}
func showPopover(sender: Any?)
{
if let button = item.button
{
popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
}
}
func closePopover(sender: Any?)
{
popover.performClose(sender)
}
//Controller code
import Cocoa
import AVFoundation
//Checking to ensure entered data is numeric
extension String
{
var isNumeric: Bool
{
let range = self.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted)
return (range == nil)
}
}
class TimerViewController: NSViewController
{
//Here's the texts fields for the user to enter content.
@IBOutlet var hourInput: NSTextField!
@IBOutlet var minuteInput: NSTextField!
@IBOutlet var secondInput: NSTextField!
//This is the label used to display the counter
@IBOutlet var initialTime: NSTextField!
//Here are the variables we're going to need
var hours = Int() //Place holder for the hours
var minutes = Int() //Place holder for the hours
var seconds = Int() //Place holder for the hours
var timer = Timer() //The timer we'll use later
var audioPlayer = AVAudioPlayer() //The audio player
var timeRemaining = Int() //Place holder for the total 'seconds' to be counted
var firstRun = Bool()
let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
override func viewDidLoad()
{
super.viewDidLoad()
getData() //Pull last saved time from Core Data and load it.
hourInput.stringValue = "(hours)" //Loading the hours into the hours field
minuteInput.stringValue = "(minutes)" //Loading the minutes into the minutes field
secondInput.stringValue = "(seconds)" //Loading the seconds into the seconds field
initialTime.stringValue = "00:00:00" //Resetting the 'counter' to 0
firstRun = true
updateStatusBar(self)
//Here we load up the audio file for the 'done' chime. If not available we print the catch
do
{
let audioPath = Bundle.main.path(forResource: "Done", ofType: "m4a")
try audioPlayer = AVAudioPlayer(contentsOf: URL(fileURLWithPath: audioPath!))
}
catch
{
print("No Joy")
}
/* if let button = item.button
{
button.image = NSImage(named: NSImage.Name("2"))
button.title = initialTime.stringValue
button.action = #selector(togglePopover(_:))
}
*/ }
}
// MARK: Storyboard instantiation
extension TimerViewController
{
static func freshController() -> TimerViewController
{
let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil)
let identifier = NSStoryboard.SceneIdentifier("TimerViewController")
guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? TimerViewController
else
{
fatalError("Why can't I find TimerViewController? - Check Main.storyboard")
}
return viewcontroller
}
}
//Button actions follow
extension TimerViewController
{
@IBAction func clearButton(_ sender: Any)
{
clearFields()
timer.invalidate()
audioPlayer.stop()
}
@IBAction func pauseButton(_ sender: Any)
{
timer.invalidate()
}
@IBAction func quitButton(_ sender: Any)
{
exit(0)
}
@IBAction func startButton(_ sender: Any)
{
grabData()
setData()
timeRemaining = (hours*3600)+(minutes*60)+seconds
if timeRemaining <= 0
{
initialTime.stringValue = "Enter Time"
}
else
{
displayTime()
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.startCountDown), userInfo: nil, repeats: true)
clearFields()
updateStatusBar(self)
}
}
}
//MARK: Other Functions
extension TimerViewController
{
func displayTime()
{
let secondsDisplay = String(format: "%02d", (timeRemaining%60))
let minutesDisplay = String(format: "%02d", (timeRemaining%3600)/60)
initialTime.stringValue = "(timeRemaining/3600):(minutesDisplay):(secondsDisplay)"
}
func grabData()
{
hours = hourInput.integerValue
minutes = minuteInput.integerValue
seconds = secondInput.integerValue
}
func clearFields()
{
hourInput.stringValue = ""
minuteInput.stringValue = ""
secondInput.stringValue = ""
initialTime.stringValue = "00:00:00"
}
func setData()
{
setHour()
setMinute()
setSecond()
}
func getData()
{
getHour()
getMinute()
getSecond()
}
@objc func showTimer(_ sender: Any?)
{
print("Are we here")
}
@objc func startCountDown()
{
timeRemaining -= 1
displayTime()
updateStatusBar(self)
print(timeRemaining)
if timeRemaining == 0
{
timer.invalidate()
audioPlayer.play()
}
}
/* func setNeedsStatusBarAppearanceUpdate()
{
button.image = NSImage(named: NSImage.Name("2"))
button.action = #selector(showTimer(_:))
}
*/
func updateStatusBar(_ sender: Any?)
{
if let button = item.button
{
button.image = NSImage(named: NSImage.Name("2"))
button.action = #selector(showTimer(_:))
button.title = initialTime.stringValue
}
//let menu = NSMenu()
//menu.addItem(NSMenuItem(title: "Clear Timer", action: #selector(AppDelegate.theDv2), keyEquivalent: "R"))
//menu.addItem(NSMenuItem(title: "Quit Timer", action: #selector(AppDelegate.quit), keyEquivalent: "Q"))
//item.menu = menu
}
}
//There's a bunch of CoreData stuff after here but I left that out. I'm just using CoreData mainly to learn how to and functional reason is to store and load the last used time
As it currently works, I get two StatusBar items instead of creating one with the AppDelegate then updating that one from the ViewController.
macos swift4 appdelegate nsviewcontroller nsstatusitem
add a comment |
I'm trying to create a Countdown Timer application that runs in the Menu Bar, with no window or dock icon. I've been building this off of mostly tutorials I find online and I know the code is kind of messy (I plan to clean up after it functions properly). The issue I'm running into. In the AppDelegate I create the StatusBar item with no issue, but I can't figure out how to update it from the viewController. It instead is creating a new StatusBar item.
//AppDelegate info
class AppDelegate: NSObject, NSApplicationDelegate
{
let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
let popover = NSPopover()
func applicationDidFinishLaunching(_ aNotification: Notification)
{
menuBarRefresh(self)
}
func menuBarRefresh(_ sender: Any?)
{
if let button = item.button
{
button.image = NSImage(named: NSImage.Name("2"))
//button.title = initialTime.stringValue
button.action = #selector(togglePopover(_:))
}
popover.contentViewController = TimerViewController.freshController()
}
@objc func togglePopover(_ sender: Any?)
{
if popover.isShown
{
closePopover(sender: sender)
}
else
{
showPopover(sender: sender)
}
}
func showPopover(sender: Any?)
{
if let button = item.button
{
popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
}
}
func closePopover(sender: Any?)
{
popover.performClose(sender)
}
//Controller code
import Cocoa
import AVFoundation
//Checking to ensure entered data is numeric
extension String
{
var isNumeric: Bool
{
let range = self.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted)
return (range == nil)
}
}
class TimerViewController: NSViewController
{
//Here's the texts fields for the user to enter content.
@IBOutlet var hourInput: NSTextField!
@IBOutlet var minuteInput: NSTextField!
@IBOutlet var secondInput: NSTextField!
//This is the label used to display the counter
@IBOutlet var initialTime: NSTextField!
//Here are the variables we're going to need
var hours = Int() //Place holder for the hours
var minutes = Int() //Place holder for the hours
var seconds = Int() //Place holder for the hours
var timer = Timer() //The timer we'll use later
var audioPlayer = AVAudioPlayer() //The audio player
var timeRemaining = Int() //Place holder for the total 'seconds' to be counted
var firstRun = Bool()
let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
override func viewDidLoad()
{
super.viewDidLoad()
getData() //Pull last saved time from Core Data and load it.
hourInput.stringValue = "(hours)" //Loading the hours into the hours field
minuteInput.stringValue = "(minutes)" //Loading the minutes into the minutes field
secondInput.stringValue = "(seconds)" //Loading the seconds into the seconds field
initialTime.stringValue = "00:00:00" //Resetting the 'counter' to 0
firstRun = true
updateStatusBar(self)
//Here we load up the audio file for the 'done' chime. If not available we print the catch
do
{
let audioPath = Bundle.main.path(forResource: "Done", ofType: "m4a")
try audioPlayer = AVAudioPlayer(contentsOf: URL(fileURLWithPath: audioPath!))
}
catch
{
print("No Joy")
}
/* if let button = item.button
{
button.image = NSImage(named: NSImage.Name("2"))
button.title = initialTime.stringValue
button.action = #selector(togglePopover(_:))
}
*/ }
}
// MARK: Storyboard instantiation
extension TimerViewController
{
static func freshController() -> TimerViewController
{
let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil)
let identifier = NSStoryboard.SceneIdentifier("TimerViewController")
guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? TimerViewController
else
{
fatalError("Why can't I find TimerViewController? - Check Main.storyboard")
}
return viewcontroller
}
}
//Button actions follow
extension TimerViewController
{
@IBAction func clearButton(_ sender: Any)
{
clearFields()
timer.invalidate()
audioPlayer.stop()
}
@IBAction func pauseButton(_ sender: Any)
{
timer.invalidate()
}
@IBAction func quitButton(_ sender: Any)
{
exit(0)
}
@IBAction func startButton(_ sender: Any)
{
grabData()
setData()
timeRemaining = (hours*3600)+(minutes*60)+seconds
if timeRemaining <= 0
{
initialTime.stringValue = "Enter Time"
}
else
{
displayTime()
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.startCountDown), userInfo: nil, repeats: true)
clearFields()
updateStatusBar(self)
}
}
}
//MARK: Other Functions
extension TimerViewController
{
func displayTime()
{
let secondsDisplay = String(format: "%02d", (timeRemaining%60))
let minutesDisplay = String(format: "%02d", (timeRemaining%3600)/60)
initialTime.stringValue = "(timeRemaining/3600):(minutesDisplay):(secondsDisplay)"
}
func grabData()
{
hours = hourInput.integerValue
minutes = minuteInput.integerValue
seconds = secondInput.integerValue
}
func clearFields()
{
hourInput.stringValue = ""
minuteInput.stringValue = ""
secondInput.stringValue = ""
initialTime.stringValue = "00:00:00"
}
func setData()
{
setHour()
setMinute()
setSecond()
}
func getData()
{
getHour()
getMinute()
getSecond()
}
@objc func showTimer(_ sender: Any?)
{
print("Are we here")
}
@objc func startCountDown()
{
timeRemaining -= 1
displayTime()
updateStatusBar(self)
print(timeRemaining)
if timeRemaining == 0
{
timer.invalidate()
audioPlayer.play()
}
}
/* func setNeedsStatusBarAppearanceUpdate()
{
button.image = NSImage(named: NSImage.Name("2"))
button.action = #selector(showTimer(_:))
}
*/
func updateStatusBar(_ sender: Any?)
{
if let button = item.button
{
button.image = NSImage(named: NSImage.Name("2"))
button.action = #selector(showTimer(_:))
button.title = initialTime.stringValue
}
//let menu = NSMenu()
//menu.addItem(NSMenuItem(title: "Clear Timer", action: #selector(AppDelegate.theDv2), keyEquivalent: "R"))
//menu.addItem(NSMenuItem(title: "Quit Timer", action: #selector(AppDelegate.quit), keyEquivalent: "Q"))
//item.menu = menu
}
}
//There's a bunch of CoreData stuff after here but I left that out. I'm just using CoreData mainly to learn how to and functional reason is to store and load the last used time
As it currently works, I get two StatusBar items instead of creating one with the AppDelegate then updating that one from the ViewController.
macos swift4 appdelegate nsviewcontroller nsstatusitem
add a comment |
I'm trying to create a Countdown Timer application that runs in the Menu Bar, with no window or dock icon. I've been building this off of mostly tutorials I find online and I know the code is kind of messy (I plan to clean up after it functions properly). The issue I'm running into. In the AppDelegate I create the StatusBar item with no issue, but I can't figure out how to update it from the viewController. It instead is creating a new StatusBar item.
//AppDelegate info
class AppDelegate: NSObject, NSApplicationDelegate
{
let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
let popover = NSPopover()
func applicationDidFinishLaunching(_ aNotification: Notification)
{
menuBarRefresh(self)
}
func menuBarRefresh(_ sender: Any?)
{
if let button = item.button
{
button.image = NSImage(named: NSImage.Name("2"))
//button.title = initialTime.stringValue
button.action = #selector(togglePopover(_:))
}
popover.contentViewController = TimerViewController.freshController()
}
@objc func togglePopover(_ sender: Any?)
{
if popover.isShown
{
closePopover(sender: sender)
}
else
{
showPopover(sender: sender)
}
}
func showPopover(sender: Any?)
{
if let button = item.button
{
popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
}
}
func closePopover(sender: Any?)
{
popover.performClose(sender)
}
//Controller code
import Cocoa
import AVFoundation
//Checking to ensure entered data is numeric
extension String
{
var isNumeric: Bool
{
let range = self.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted)
return (range == nil)
}
}
class TimerViewController: NSViewController
{
//Here's the texts fields for the user to enter content.
@IBOutlet var hourInput: NSTextField!
@IBOutlet var minuteInput: NSTextField!
@IBOutlet var secondInput: NSTextField!
//This is the label used to display the counter
@IBOutlet var initialTime: NSTextField!
//Here are the variables we're going to need
var hours = Int() //Place holder for the hours
var minutes = Int() //Place holder for the hours
var seconds = Int() //Place holder for the hours
var timer = Timer() //The timer we'll use later
var audioPlayer = AVAudioPlayer() //The audio player
var timeRemaining = Int() //Place holder for the total 'seconds' to be counted
var firstRun = Bool()
let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
override func viewDidLoad()
{
super.viewDidLoad()
getData() //Pull last saved time from Core Data and load it.
hourInput.stringValue = "(hours)" //Loading the hours into the hours field
minuteInput.stringValue = "(minutes)" //Loading the minutes into the minutes field
secondInput.stringValue = "(seconds)" //Loading the seconds into the seconds field
initialTime.stringValue = "00:00:00" //Resetting the 'counter' to 0
firstRun = true
updateStatusBar(self)
//Here we load up the audio file for the 'done' chime. If not available we print the catch
do
{
let audioPath = Bundle.main.path(forResource: "Done", ofType: "m4a")
try audioPlayer = AVAudioPlayer(contentsOf: URL(fileURLWithPath: audioPath!))
}
catch
{
print("No Joy")
}
/* if let button = item.button
{
button.image = NSImage(named: NSImage.Name("2"))
button.title = initialTime.stringValue
button.action = #selector(togglePopover(_:))
}
*/ }
}
// MARK: Storyboard instantiation
extension TimerViewController
{
static func freshController() -> TimerViewController
{
let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil)
let identifier = NSStoryboard.SceneIdentifier("TimerViewController")
guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? TimerViewController
else
{
fatalError("Why can't I find TimerViewController? - Check Main.storyboard")
}
return viewcontroller
}
}
//Button actions follow
extension TimerViewController
{
@IBAction func clearButton(_ sender: Any)
{
clearFields()
timer.invalidate()
audioPlayer.stop()
}
@IBAction func pauseButton(_ sender: Any)
{
timer.invalidate()
}
@IBAction func quitButton(_ sender: Any)
{
exit(0)
}
@IBAction func startButton(_ sender: Any)
{
grabData()
setData()
timeRemaining = (hours*3600)+(minutes*60)+seconds
if timeRemaining <= 0
{
initialTime.stringValue = "Enter Time"
}
else
{
displayTime()
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.startCountDown), userInfo: nil, repeats: true)
clearFields()
updateStatusBar(self)
}
}
}
//MARK: Other Functions
extension TimerViewController
{
func displayTime()
{
let secondsDisplay = String(format: "%02d", (timeRemaining%60))
let minutesDisplay = String(format: "%02d", (timeRemaining%3600)/60)
initialTime.stringValue = "(timeRemaining/3600):(minutesDisplay):(secondsDisplay)"
}
func grabData()
{
hours = hourInput.integerValue
minutes = minuteInput.integerValue
seconds = secondInput.integerValue
}
func clearFields()
{
hourInput.stringValue = ""
minuteInput.stringValue = ""
secondInput.stringValue = ""
initialTime.stringValue = "00:00:00"
}
func setData()
{
setHour()
setMinute()
setSecond()
}
func getData()
{
getHour()
getMinute()
getSecond()
}
@objc func showTimer(_ sender: Any?)
{
print("Are we here")
}
@objc func startCountDown()
{
timeRemaining -= 1
displayTime()
updateStatusBar(self)
print(timeRemaining)
if timeRemaining == 0
{
timer.invalidate()
audioPlayer.play()
}
}
/* func setNeedsStatusBarAppearanceUpdate()
{
button.image = NSImage(named: NSImage.Name("2"))
button.action = #selector(showTimer(_:))
}
*/
func updateStatusBar(_ sender: Any?)
{
if let button = item.button
{
button.image = NSImage(named: NSImage.Name("2"))
button.action = #selector(showTimer(_:))
button.title = initialTime.stringValue
}
//let menu = NSMenu()
//menu.addItem(NSMenuItem(title: "Clear Timer", action: #selector(AppDelegate.theDv2), keyEquivalent: "R"))
//menu.addItem(NSMenuItem(title: "Quit Timer", action: #selector(AppDelegate.quit), keyEquivalent: "Q"))
//item.menu = menu
}
}
//There's a bunch of CoreData stuff after here but I left that out. I'm just using CoreData mainly to learn how to and functional reason is to store and load the last used time
As it currently works, I get two StatusBar items instead of creating one with the AppDelegate then updating that one from the ViewController.
macos swift4 appdelegate nsviewcontroller nsstatusitem
I'm trying to create a Countdown Timer application that runs in the Menu Bar, with no window or dock icon. I've been building this off of mostly tutorials I find online and I know the code is kind of messy (I plan to clean up after it functions properly). The issue I'm running into. In the AppDelegate I create the StatusBar item with no issue, but I can't figure out how to update it from the viewController. It instead is creating a new StatusBar item.
//AppDelegate info
class AppDelegate: NSObject, NSApplicationDelegate
{
let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
let popover = NSPopover()
func applicationDidFinishLaunching(_ aNotification: Notification)
{
menuBarRefresh(self)
}
func menuBarRefresh(_ sender: Any?)
{
if let button = item.button
{
button.image = NSImage(named: NSImage.Name("2"))
//button.title = initialTime.stringValue
button.action = #selector(togglePopover(_:))
}
popover.contentViewController = TimerViewController.freshController()
}
@objc func togglePopover(_ sender: Any?)
{
if popover.isShown
{
closePopover(sender: sender)
}
else
{
showPopover(sender: sender)
}
}
func showPopover(sender: Any?)
{
if let button = item.button
{
popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
}
}
func closePopover(sender: Any?)
{
popover.performClose(sender)
}
//Controller code
import Cocoa
import AVFoundation
//Checking to ensure entered data is numeric
extension String
{
var isNumeric: Bool
{
let range = self.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted)
return (range == nil)
}
}
class TimerViewController: NSViewController
{
//Here's the texts fields for the user to enter content.
@IBOutlet var hourInput: NSTextField!
@IBOutlet var minuteInput: NSTextField!
@IBOutlet var secondInput: NSTextField!
//This is the label used to display the counter
@IBOutlet var initialTime: NSTextField!
//Here are the variables we're going to need
var hours = Int() //Place holder for the hours
var minutes = Int() //Place holder for the hours
var seconds = Int() //Place holder for the hours
var timer = Timer() //The timer we'll use later
var audioPlayer = AVAudioPlayer() //The audio player
var timeRemaining = Int() //Place holder for the total 'seconds' to be counted
var firstRun = Bool()
let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
override func viewDidLoad()
{
super.viewDidLoad()
getData() //Pull last saved time from Core Data and load it.
hourInput.stringValue = "(hours)" //Loading the hours into the hours field
minuteInput.stringValue = "(minutes)" //Loading the minutes into the minutes field
secondInput.stringValue = "(seconds)" //Loading the seconds into the seconds field
initialTime.stringValue = "00:00:00" //Resetting the 'counter' to 0
firstRun = true
updateStatusBar(self)
//Here we load up the audio file for the 'done' chime. If not available we print the catch
do
{
let audioPath = Bundle.main.path(forResource: "Done", ofType: "m4a")
try audioPlayer = AVAudioPlayer(contentsOf: URL(fileURLWithPath: audioPath!))
}
catch
{
print("No Joy")
}
/* if let button = item.button
{
button.image = NSImage(named: NSImage.Name("2"))
button.title = initialTime.stringValue
button.action = #selector(togglePopover(_:))
}
*/ }
}
// MARK: Storyboard instantiation
extension TimerViewController
{
static func freshController() -> TimerViewController
{
let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil)
let identifier = NSStoryboard.SceneIdentifier("TimerViewController")
guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? TimerViewController
else
{
fatalError("Why can't I find TimerViewController? - Check Main.storyboard")
}
return viewcontroller
}
}
//Button actions follow
extension TimerViewController
{
@IBAction func clearButton(_ sender: Any)
{
clearFields()
timer.invalidate()
audioPlayer.stop()
}
@IBAction func pauseButton(_ sender: Any)
{
timer.invalidate()
}
@IBAction func quitButton(_ sender: Any)
{
exit(0)
}
@IBAction func startButton(_ sender: Any)
{
grabData()
setData()
timeRemaining = (hours*3600)+(minutes*60)+seconds
if timeRemaining <= 0
{
initialTime.stringValue = "Enter Time"
}
else
{
displayTime()
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.startCountDown), userInfo: nil, repeats: true)
clearFields()
updateStatusBar(self)
}
}
}
//MARK: Other Functions
extension TimerViewController
{
func displayTime()
{
let secondsDisplay = String(format: "%02d", (timeRemaining%60))
let minutesDisplay = String(format: "%02d", (timeRemaining%3600)/60)
initialTime.stringValue = "(timeRemaining/3600):(minutesDisplay):(secondsDisplay)"
}
func grabData()
{
hours = hourInput.integerValue
minutes = minuteInput.integerValue
seconds = secondInput.integerValue
}
func clearFields()
{
hourInput.stringValue = ""
minuteInput.stringValue = ""
secondInput.stringValue = ""
initialTime.stringValue = "00:00:00"
}
func setData()
{
setHour()
setMinute()
setSecond()
}
func getData()
{
getHour()
getMinute()
getSecond()
}
@objc func showTimer(_ sender: Any?)
{
print("Are we here")
}
@objc func startCountDown()
{
timeRemaining -= 1
displayTime()
updateStatusBar(self)
print(timeRemaining)
if timeRemaining == 0
{
timer.invalidate()
audioPlayer.play()
}
}
/* func setNeedsStatusBarAppearanceUpdate()
{
button.image = NSImage(named: NSImage.Name("2"))
button.action = #selector(showTimer(_:))
}
*/
func updateStatusBar(_ sender: Any?)
{
if let button = item.button
{
button.image = NSImage(named: NSImage.Name("2"))
button.action = #selector(showTimer(_:))
button.title = initialTime.stringValue
}
//let menu = NSMenu()
//menu.addItem(NSMenuItem(title: "Clear Timer", action: #selector(AppDelegate.theDv2), keyEquivalent: "R"))
//menu.addItem(NSMenuItem(title: "Quit Timer", action: #selector(AppDelegate.quit), keyEquivalent: "Q"))
//item.menu = menu
}
}
//There's a bunch of CoreData stuff after here but I left that out. I'm just using CoreData mainly to learn how to and functional reason is to store and load the last used time
As it currently works, I get two StatusBar items instead of creating one with the AppDelegate then updating that one from the ViewController.
macos swift4 appdelegate nsviewcontroller nsstatusitem
macos swift4 appdelegate nsviewcontroller nsstatusitem
asked Jan 1 at 11:17
ZardozZardoz
33
33
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Yup... Id-10-t error here. Just had to declare 'item' outside the class and all is well. After getting some good sleep and time away from the computer I realized I was not declaring 'item' globally.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53994995%2fhow-to-update-a-status-item-created-by-appdelegate-from-nsviewcontroller%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Yup... Id-10-t error here. Just had to declare 'item' outside the class and all is well. After getting some good sleep and time away from the computer I realized I was not declaring 'item' globally.
add a comment |
Yup... Id-10-t error here. Just had to declare 'item' outside the class and all is well. After getting some good sleep and time away from the computer I realized I was not declaring 'item' globally.
add a comment |
Yup... Id-10-t error here. Just had to declare 'item' outside the class and all is well. After getting some good sleep and time away from the computer I realized I was not declaring 'item' globally.
Yup... Id-10-t error here. Just had to declare 'item' outside the class and all is well. After getting some good sleep and time away from the computer I realized I was not declaring 'item' globally.
answered Jan 2 at 12:31
ZardozZardoz
33
33
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53994995%2fhow-to-update-a-status-item-created-by-appdelegate-from-nsviewcontroller%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown