How to give an NSPopover focus when NSStatusItem is clicked? - swift

I am building a macOS menubar app in Swift, using an NSStatusItem, which opens an NSPopover when the NSStatusItem's button is clicked.
How can I also give the NSPopover focus? Currently, the user needs to click on the popover to focus it, but I want to grab focus programmatically.
Thanks in Advance

The solution is to call makeKey() on the owning window.
This can be done either from the main NSApplicationDelegate, e.g.
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Other setup
popover.contentViewController?.view.window?.makeKey()
}
Or from the relevant NSViewController, e.g.
override func viewDidAppear() {
super.viewDidAppear()
view.window?.makeKey()
}
Documentation is here

Related

Keyboard does not open when clicking on UITextfield

I create sign in page with swift programmatically coding. I tried simulator and device but keyboard did not opened when clicked on textfied.
when I write code in viewController with stroyboard, keyboard had opened. But, without using storyboard, keyboard is not opening.
Did you set the TextField's delegate? In the Storyboard you must have, but in code that is sometimes forgotten.
class ViewController: UIViewController, UITextFieldDelegate {
let textField = UITextField()
func viewDidLoad() {
super.viewDidLoad()
textfield.delegate = self // Did you do this?
}
}
If you are using simulator then you must go to I/O -> Keyboard -> Toggle software keyboard.
If you are using physical device then through code you need to set as as first responser as below:
textfieldName.becomeFirstResponder()

Clicking the Button will move to the next controller?

How to Move to the Next Controller with a single click of a Button?
There is no data transfer, only one click of button and it will proceed to the next controller.
I created a controller named "ViewIntro" which is the initial controller. It's basically a Welcome Screen and there is a button at the bottom.
Once the button is clicked, it will proceed to the viewController which is the original controller whenever we start an xcode project I forgot to make the viewController as my welcome screen
Anyways, here is my current code of my ViewIntro:
`import Foundation
import UIKit
class ViewIntro : UIViewController{
#IBOutlet weak var btnEnter: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}`
I also had connected the ViewIntro to ViewController through identifier as shown in the attached image.
Right click your button and drag it to your controller. Just like creating an IBOutlet but you should select Action mode. Afret creating an IBAction for your button, just add this code into it:
self.performSegue(withIdentifier: "showMain", sender: nil)

Detect maximize/minimize window event and do it programmatically

How detect Minimize/Maximize window and do this programmatically. I know that i need use NSWindowdelegate, but:
class AppDelegate: NSObject, NSApplicationDelegate, NSWindowdelegate {
func windowWillMiniaturize(_ notification: Notification) {
print("1")
}
}
This not working. And how to maximize/minimize programmatically have no idea.
It is all in Apples documentation on NSWindowDelegate: https://developer.apple.com/reference/appkit/nswindowdelegate
You can implement in you class that is set as delegate for your window:
func windowWillMiniaturize(Notification)
Tells the delegate that the window is about to be minimized.
func windowDidMiniaturize(Notification)
Tells the delegate that the window has been minimized.
func windowDidDeminiaturize(Notification)
Tells the delegate that the window has been deminimized.
NSWindow has methods - easily to find when visiting the documentation: https://developer.apple.com/reference/appkit/nswindow
You can call from anywhere on your window:
func performMiniaturize(Any?)
Simulates the user clicking the minimize button by momentarily highlighting the button, then minimizing the window.
func miniaturize(Any?)
Removes the window from the screen list and displays the minimized window in the Dock.
func deminiaturize(Any?)
De-minimizes the window.

OSX Swift - Show modal second window

I am trying to display a second window after a button click:
var winJ:WinJo // other window NSViewController
#IBAction func BtnNewWin(sender: AnyObject) {
winJ = WinJo()
winJ.showWindow(self)
}
This works fine but I want the new window to be modal. I accomplished this with the Xcode designer but I couldn't figure out how to do this in code.
After I was pointed in the right direction I found the solution to my problem:
NSApp.runModalForWindow(winJ.window!)
Where NSApp is actually the instance of NSApplication.
And very important in the second window:
func windowWillClose(notification: NSNotification) {
NSApp.stopModal()
}
Otherwise your main window will be blocked after closing the second.

Tooltip doesn't show up again

I have a Mac app that exclusively live on the menu bar. It has a progress bar and a label. The label shows the percentage of the progress of the task that's being carried out. I want to show more info when the user hovers the mouse pointer over the progress indicator.
When I set the tooltip initially and hover over, it displays without an issue.
But if I head over somewhere and open the menu app again and hover over again, the tooltip doesn't come up. I can't figure out why. Here's my code.
ProgressMenuController.swift
import Cocoa
class ProgressMenuController: NSObject {
#IBOutlet weak var menu: NSMenu!
#IBOutlet weak var progressView: ProgressView!
let menuItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSVariableStatusItemLength)
var progressMenuItem: NSMenuItem!
override func awakeFromNib() {
menuItem.menu = menu
menuItem.image = NSImage(named: "icon")
progressMenuItem = menu.itemWithTitle("Progress")
progressMenuItem.view = progressView
progressView.update(42)
}
#IBAction func quitClicked(sender: NSMenuItem) {
NSApplication.sharedApplication().terminate(self)
}
}
ProgressView.swift
import Cocoa
class ProgressView: NSView {
#IBOutlet weak var progressIndicator: NSProgressIndicator!
#IBOutlet weak var progressPercentageLabel: NSTextField!
func update(value: Double) {
dispatch_async(dispatch_get_main_queue()) {
self.progressIndicator.doubleValue = value
self.progressIndicator.toolTip = "3 out of 5 files has been copied"
self.progressPercentageLabel.stringValue = "\(value)%"
}
}
}
This is a demo app similar to my actual app. So the update() function is called only once and the values are hardcoded. But in my actual app, the progress is tracked periodically and the update() function gets called with it to update the values. The label's percentage value and the progress indicator's value get updated without a problem. The issue is only with the tooltip.
Is this expected behavior or am I missing something?
I ran into the same problem, and realized the issue was that only the currently focused window will display tool-tips, but after my app lost focus, it would never get it back. Focus usually transfers automatically when the user clicks on your window, but it isn't automatic for menu bar apps. Using NSApp.activate, you can regain focus onto your app:
override func viewWillAppear() {
super.viewWillAppear()
NSApp.activate(ignoringOtherApps: true)
}
sanche's answer worked for me as well, but I ended up moving the tool tips to my NSMenuItems instead so I wouldn't have to steal focus from the foreground app. NSMenuItem's tool tips seem to be handled as a special case so the app doesn't need to be focused.
This solution would make the tool tip apply to everything in the menu item and appear next to the menu rather than over it, but it looks like that might not be a problem in your case.