Xcode NSStatusBar Item not appearing - swift

I'm trying to add an item to the status bar, but when I launch the app the item only appears in the top left for a split second and then quickly disappears.
I've looked through the documentation and I can see things have changed recently e.g. statusItem.title has become statusItem.button?.title. But don't seem to be missing anything else. Any help?
Here's my code:
var statusItem : NSStatusItem? = nil
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
statusItem.button?.title = "Connect!"
}

Ah brilliant. That's worked! Thanks Saleh. After playing around with both our codes, mine seemed to work with the var declaration at the top and without NSMenuDelegate instance. My issue seems to be that I was saying :
let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
All I had to do to make it work was remove the 'let' and just say:
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)

AppDelegate should be an instance of NSMenuDelegate
Define the statusItem at creation
Setup the button title in the applicationDidFinishLaunching callback
class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.variableLength)
func applicationDidFinishLaunching(_ aNotification: Notification) {
if let button = statusItem.button {
//button.image = NSImage(named:NSImage.Name("StatusBarButtonImage"))
button.title = "connect"
//button.action = #selector(doSomething(_:))
}
}

Related

Can't hide NSStatusItem from status bar?

I'm trying to add an option to my app settings to hide the icon from the status bar. It currently looks like this inside my AppDelegate :
func applicationDidFinishLaunching(_ notification: Notification) {
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
statusItem?.button?.image = NSImage(systemSymbolName: "paperplane.fill", accessibilityDescription: nil)
if let menu = menu {
statusItem?.menu = menu
}
}
I'm trying to hide it from a preference pane view controller with the following code :
#IBAction func hideicon(_ sender: Any) {
if hideicon.state.rawValue == 1 {
NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength).isVisible = false
} else {
NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength).isVisible = true
}
}
But the button is still showing. Trying to edit the button image isn't working either.
What am I missing here?
This :
#IBAction func hideicon(_ sender: Any) {
if hideicon.state.rawValue == 1 {
let appDelegate = NSApplication.shared.delegate as! AppDelegate
appDelegate.statusItem?.isVisible = false
} else {
let appDelegate = NSApplication.shared.delegate as! AppDelegate
appDelegate.statusItem?.isVisible = true
}
}
Simply solved my issue.

How to reopen an macos App using menubar button

I created an app with a menubar button using swift and storyboard, when I click the close button the window closed and the menubar button still sits on the menubar, that's good. What I want to do next is reopen the window by clicking the menubar button. After searching I figured out I can use this code to bring it to the front, but it only works when the window is still open. How can I bring it back when it is closed or miniatured?
NSApplication.shared.activate(ignoringOtherApps: true)
This the appDelegate
class AppDelegate: NSObject, NSApplicationDelegate {
private var statusItem: NSStatusItem!
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
statusItem = NSStatusBar.system.statusItem(withLength: 16.0)
if let button = statusItem.button {
button.image = NSImage(named: "remote-control")
button.image?.size = NSSize(width: 16.0, height: 16.0)
button.image?.isTemplate = true
button.action = #selector(bringToFront(sender:))
}
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
print("terminate")
}
func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
return true
}
#objc func bringToFront(sender: AnyObject?) {
NSApplication.shared.activate(ignoringOtherApps: true)
NSApp.windows.last?.makeKeyAndOrderFront(nil)
}}
This is the windowcontroller
class MainWindowController: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
window?.title = ""
let styleMask: NSWindow.StyleMask = [.closable, .titled, .miniaturizable]
window?.styleMask = styleMask
}}
Thanks
I got it.
In appdelegate use deminiaturize function does exactly what I want.
for window in NSApp.windows {
window.deminiaturize(nil)
}
Since I only have one window but NSApp.windows has two members, I think I can deminiatureize all the windows.

Display an icon and text on NSStatusBar for macOS using Swift

I would like to display an icon and some texts to its right on a NSStatusBar.
The code I'm using, as seen below, displays the icon and the text overlapping.
This is an example of I'm trying to emulate:
And here's my current code for reference:
let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.variableLength)
var preferencesWindow: NSWindowController?
func applicationDidFinishLaunching(_ aNotification: Notification) {
if let button = statusItem.button {
button.image = NSImage(named:NSImage.Name("StatusBarButtonImage"))
button.title = "..."
}
initMenu()
}

Swift+Macos Auto close popover window when focus is lost

I am writing a small app that display an icon in the menu bar with a popup view.
I followed https://github.com/twostraws/SwiftOnSundays/tree/master/013%20TextTransformer as an example.
One difference I am seeing in my test app is the popover view controller is not getting dismissed when view loses focus.
this is my app delegate,
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
let popupOver = NSPopover()
#IBOutlet weak var menu: NSMenu!
func applicationDidFinishLaunching(_ aNotification: Notification) {
statusItem.button?.title = "FT";
statusItem.button?.target = self;
statusItem.button?.action = #selector(showMenu)
let storyBoard = NSStoryboard(name: "Main", bundle: nil)
guard let viewController = storyBoard.instantiateController(withIdentifier: "FTViewController") as? ViewController else {
fatalError("Unable to find 'FTViewController'")
}
popupOver.contentViewController = viewController
popupOver.behavior = .semitransient
}
func applicationDidResignActive(_ notification: Notification) {
popupOver.close()
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
#objc func showMenu() {
if(popupOver.isShown) {
popupOver.close()
}
else {
guard let statusButton = statusItem.button else {
fatalError("Unable to find status button")
}
popupOver.show(relativeTo: statusButton.bounds, of: statusButton, preferredEdge: .maxY)
}
}
}
I tried adding applicationDidResignActive but that's getting triggered only when the application loses focus so if i directly click the menu bar item and click else where on screen I am not getting that event. The sampleapp i referenced doesnt seem to hookup for these events but still works as expected.
I am just starting swift ui programming so couldnt figure out what I am missing here.
Not sure if you're still looking for a solution here, but I've just got stuck with the same problem and I found this example which seems to do the job. Hope this helps.

swift mac osx NSButton is not responding until a long press

I am having a weird issue with a button. So I have a NSViewController with many subviews in it. When I click a button, a new NSView with click gestures and buttons is added on top. But I can't press any of them, they don't respond unless a click for 2 seconds and then release. I've tried disabling the gestures of the holder but it didn't work. Any suggestions?
Well, some of the rest of us do. In my case, it's for buttons on a view in a sheet, so "many subviews" isn't likely it. My view controller for the sheet is about 100 lines. Still debugging...
At present the VC is as follows. The snp.makeConstraints calls are for SnapKit (from GitHub)
#objc
class ThreadEditSheetViewController: NSViewController {
/// The container for the graphics view
#IBOutlet var sheetView: NSView!
/// The information packet initialized by the invoking view controller
var info: ThreadEditInfo!
/// API
override func viewDidLoad() {
super.viewDidLoad()
}
/// API
override func viewWillAppear() {
guard let gvc = (try? self.bundleLoader(id: "GraphicsViewController")) as? GraphicsViewController else {
fatalUserAlert(error: AppError.UIConstructionFailure, message: "Can't find GraphicsViewController for ThreadEditSheetViewController")}
let gv = gvc.view
self.view.addSubview(gv)
// Spaces in title text move it left to avoid visual overlap with scroll bar. Don't know how to do it with
// constraints given the scrolling view
let done = makeButton(gvc: gvc, title: "done ", action: #selector(doneEditing(_:)))
done.snp.makeConstraints{ (make) in
make.top.equalTo(gv).offset(-5)
make.right.equalTo(gv).offset(-5)
}
let cancel = makeButton(gvc: gvc, title: "cancel", action: #selector(cancelEditing(_:)))
cancel.snp.makeConstraints{ (make) in
make.top.equalTo(gv).offset(-5)
make.left.equalTo(gv).offset(5)
}
self.view.becomeFirstResponder()
super.viewWillAppear()
return
}
func makeButton(gvc: NSViewController, title: String, action: Selector) -> NSButton {
let button = NSButton(title: title, target: self, action: action)
let gv = gvc.view
gv.addSubview(button)
button.backgroundColor = .clear
button.setButtonType(.momentaryChange)
button.isTransparent = true
return button
}
#objc
func doneEditing(_ sender: Any) {
self.dismissViewController(self)
}
#objc
func cancelEditing(_ sender: Any) {
self.dismissViewController(self)
}
}