Can't hide NSStatusItem from status bar? - swift

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.

Related

Trying to switch which photo pops up depending on button clicked Xcode

I am making an app that will display a random quote from a stoic philosopher. Right now, I am stuck on trying to make the correct picture pop up. (User clicks on a Button with the philosopher's name on it, and then a new view pops up with an image of the philosopher and a random quote by him).
class ViewController: UIViewController {
var allQuotes = [String]()
var pictures = [String]()
#IBOutlet var Epictetus: UIButton!
#IBOutlet var Seneca: UIButton!
#IBOutlet var MarcusAurelius: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Create a constant fm and assign it the value returned by FileManager.default (built in system type)
let fm = FileManager.default
// Declares a new constant called path that sets the resource path of ours apps buddle.
// A bundle is a directory containing our compiled program and all our assets
let path = Bundle.main.resourcePath!
// items array will be a constant collection of the names of all the files found in the directory of our app
let items = try! fm.contentsOfDirectory(atPath: path)
// create a loop to go through all of our items...
for item in items {
if item.hasSuffix("jpg"){
pictures.append(item)
}
}
print(pictures)
title = "Stoicism"
if let stoicQuotesURL = Bundle.main.url(forResource: "quotes", withExtension: "txt"){
if let stoicQuotes = try? String(contentsOf: stoicQuotesURL) {
allQuotes = stoicQuotes.components(separatedBy: "\n\n")
}
}
}
#IBAction func buttonTapped(_ sender: UIButton) {
if sender.tag == 0 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[0]
navigationController?.pushViewController(vc, animated: true)
}
}
else if sender.tag == 1 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[1]
navigationController?.pushViewController(vc, animated: true)
}
}
else if sender.tag == 2 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[2]
navigationController?.pushViewController(vc, animated: true)
}
}
}
}
That's the code for my main viewController.
import UIKit
class PictureViewController: UIViewController {
#IBOutlet var picture: UIImageView!
#IBOutlet var imageView: UIImageView!
var selectedImage: String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if let imageToLoad = selectedImage {
imageView.image = UIImage(named: imageToLoad)
}
}
override func viewWillAppear(_ animated: Bool) {
// doing it for the parent class
super.viewWillAppear(animated)
// if its a nav Cont then it will hide bars on tap...
}
// now make sure it turns off when you go back to the main screen
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
That's the code for the viewController that has the imageView. Right now, the image that's popping up is always the preset (Marcus Aurelius), even though my code looks correct to me. Obviously it isn't (also, I've already debugged and ensured through print statements that the jpg files add to the pictures array correctly).
Any help would be appreciated.
First of all, this code is really silly:
#IBAction func buttonTapped(_ sender: UIButton) {
if sender.tag == 0 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[0]
navigationController?.pushViewController(vc, animated: true)
}
}
else if sender.tag == 1 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[1]
navigationController?.pushViewController(vc, animated: true)
}
}
else if sender.tag == 2 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[2]
navigationController?.pushViewController(vc, animated: true)
}
}
}
Do you see that everything in those lines is identical except for the numbers? So make the number a variable:
#IBAction func buttonTapped(_ sender: UIButton) {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
print(sender.tag)
vc.selectedImage = pictures[sender.tag]
navigationController?.pushViewController(vc, animated: true)
}
}
See how much shorter and clearer that is? Okay, I've also added a print statement. This will print the tag to the console. You need to make sure that your buttons do have the right tags. If they do, your code should work.

Shortcut Items - Perform Segue

I'm trying to add a shortcut item to my app. I have the item appearing, and it's responding but can't work out how to get the segue to work. I have it going to the right tab but need to go to the root view and perform a segue from there.
The segue is already setup on the ProjectList view controller and its called "addProject"
My view storyboard is setup as so:
UITabViewController -> UINavigationController-> UITableViewController (ProjectList) -> Other additional views
func applicationDidBecomeActive(_ application: UIApplication) {
if let shortcutItem = shortcutItemToProcess {
if shortcutItem.type == "addProject" {
if let window = self.window, let tabBar : UITabBarController = window.rootViewController as? UITabBarController {
tabBar.selectedIndex = 0
}
}
shortcutItemToProcess = nil
}
}
Solved with
func applicationDidBecomeActive(_ application: UIApplication) {
if let shortcutItem = shortcutItemToProcess {
if shortcutItem.type == "addProject" {
guard let window = self.window else { return }
guard let tabBar = window.rootViewController as? UITabBarController else { return }
guard let navCon = tabBar.viewControllers?[0] as? UINavigationController else { return }
guard let projectList = navCon.rootViewController as? ProjectList else { return }
projectList.performSegue(withIdentifier: "addProject", sender: nil)
tabBar.selectedIndex = 0
}
shortcutItemToProcess = nil
}
}

How to check if the window is open or not?

I am opening a window say "Window2" from main menu item(Command 2 under Window) . So, if the menu item is clicked again it opens the "Window2" again instead of making the existing window the key window and disabling corresponding menu item. Below is my effort on implementing that in my AppDelegate class, as variable "lmWindowController" always returning nil, instances of window2 is getting opened multiple times, what am I missing here?
class AppDelegate: NSObject, NSApplicationDelegate {
var lmWindowController: LocalisationMappingWindowController?
func applicationDidFinishLaunching(_ notification: Notification) {
}
#IBAction func showLocalisationMappingWindowController(_ sender: Any) {
if (!(lmWindowController != nil)) {
let storyboard = NSStoryboard(name: NSStoryboard.Name(rawValue: "LocalisationMapping"), bundle: Bundle.main)
if let windowController: NSWindowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "LocalisationMappingWindowController")) as? NSWindowController{
windowController.showWindow(windowController.window)
windowController.window?.makeKeyAndOrderFront(nil)
}
} else {
lmWindowController?.window?.makeKeyAndOrderFront(nil)
}
}
override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
var enable = self.responds(to: menuItem.action)
if menuItem.action == #selector(showLocalisationMappingWindowController(_:)) {
for window in NSApplication.shared.windows {
if window.title == "Localization Mapping" {
enable = false
}
}
}
return enable
}
}
In showLocalisationMappingWindowController a new windowController is loaded but lmWindowController isn't changed. Add lmWindowController = windowController.
#IBAction func showLocalisationMappingWindowController(_ sender: Any) {
if (!(lmWindowController != nil)) {
let storyboard = NSStoryboard(name: NSStoryboard.Name(rawValue: "LocalisationMapping"), bundle: Bundle.main)
if let windowController: NSWindowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "LocalisationMappingWindowController")) as? NSWindowController{
windowController.showWindow(windowController.window)
windowController.window?.makeKeyAndOrderFront(nil)
lmWindowController = windowController
}
} else {
lmWindowController?.window?.makeKeyAndOrderFront(nil)
}
}

How do I open a setting menù from a Status Item on right-click? Swift on MacOS [duplicate]

I’m building a status bar app and want to call different actions depending on if the user clicked left or right. Here’s what I have so far:
var statusItem = NSStatusBar.system().statusItem(withLength: -1)
statusItem.action = #selector(AppDelegate.doSomeAction(sender:))
let leftClick = NSEventMask.leftMouseDown
let rightClick = NSEventMask.rightMouseDown
statusItem.button?.sendAction(on: leftClick)
statusItem.button?.sendAction(on: rightClick)
func doSomeAction(sender: NSStatusItem) {
print("hello world")
}
My function is not called and I couldn’t find our why. I appreciate any help!
Have you tried:
button.sendAction(on: [.leftMouseUp, .rightMouseUp])
Then seeing which mouse button was pressed in the doSomeAction() function?
So it will look something like...
let statusItem = NSStatusBar.system().statusItem(withLength: NSSquareStatusItemLength)
func applicationDidFinishLaunching(_ aNotification: Notification) {
if let button = statusItem.button {
button.action = #selector(self.doSomeAction(sender:))
button.sendAction(on: [.leftMouseUp, .rightMouseUp])
}
}
func doSomeAction(sender: NSStatusItem) {
let event = NSApp.currentEvent!
if event.type == NSEvent.EventType.rightMouseUp {
// Right button click
} else {
// Left button click
}
}
Thanks to #dbrownjave for noticing the change in Swift 4 from NSEventType.rightMouseUp to NSEvent.EventType.rightMouseUp.
https://github.com/craigfrancis/datetime/blob/master/xcode/DateTime/AppDelegate.swift
Updated: SWIFT 4
I've updated (Craig Francis) answer
func doSomeAction(sender: NSStatusItem) {
let event = NSApp.currentEvent!
if event.type == NSEvent.EventType.rightMouseUp{
// Right button click
} else {
// Left button click
}

Detect left and right click events on NSStatusItem (Swift)

I’m building a status bar app and want to call different actions depending on if the user clicked left or right. Here’s what I have so far:
var statusItem = NSStatusBar.system().statusItem(withLength: -1)
statusItem.action = #selector(AppDelegate.doSomeAction(sender:))
let leftClick = NSEventMask.leftMouseDown
let rightClick = NSEventMask.rightMouseDown
statusItem.button?.sendAction(on: leftClick)
statusItem.button?.sendAction(on: rightClick)
func doSomeAction(sender: NSStatusItem) {
print("hello world")
}
My function is not called and I couldn’t find our why. I appreciate any help!
Have you tried:
button.sendAction(on: [.leftMouseUp, .rightMouseUp])
Then seeing which mouse button was pressed in the doSomeAction() function?
So it will look something like...
let statusItem = NSStatusBar.system().statusItem(withLength: NSSquareStatusItemLength)
func applicationDidFinishLaunching(_ aNotification: Notification) {
if let button = statusItem.button {
button.action = #selector(self.doSomeAction(sender:))
button.sendAction(on: [.leftMouseUp, .rightMouseUp])
}
}
func doSomeAction(sender: NSStatusItem) {
let event = NSApp.currentEvent!
if event.type == NSEvent.EventType.rightMouseUp {
// Right button click
} else {
// Left button click
}
}
Thanks to #dbrownjave for noticing the change in Swift 4 from NSEventType.rightMouseUp to NSEvent.EventType.rightMouseUp.
https://github.com/craigfrancis/datetime/blob/master/xcode/DateTime/AppDelegate.swift
Updated: SWIFT 4
I've updated (Craig Francis) answer
func doSomeAction(sender: NSStatusItem) {
let event = NSApp.currentEvent!
if event.type == NSEvent.EventType.rightMouseUp{
// Right button click
} else {
// Left button click
}