Anwendungen in der Menüleiste sind MacOS-Benutzern seit langem bekannt. Einige dieser Anwendungen haben einen „normalen“ Teil, andere befinden sich nur in der Menüleiste.
In diesem Handbuch schreiben Sie eine Anwendung, in der mehrere Zitate berühmter Personen in einem Popup-Fenster angezeigt werden. Beim Erstellen dieser Anwendung lernen Sie Folgendes:
- Anwendungssymbol in der Menüleiste zuweisen
- Die Anwendung wird nur in der Menüleiste gehostet
- Benutzerdefiniertes Menü hinzufügen
- Zeigen Sie auf Wunsch des Benutzers ein Popup-Fenster an und blenden Sie es bei Bedarf mithilfe der Ereignisüberwachung aus
Hinweis: In diesem Handbuch wird davon ausgegangen, dass Sie mit Swift und macOS vertraut sind.
Erste Schritte
Starten Sie Xcode. Wählen Sie als Nächstes im Menü
Datei / Neu / Projekt ... die Vorlage
macOS / Anwendung / Kakao-App aus und klicken Sie auf
Weiter .
Geben Sie im nächsten Bildschirm Angebote als
Produktnamen ein und wählen Sie Ihren
Organisationsnamen und Ihre
Organisationskennung aus . Stellen Sie dann sicher, dass Swift als Anwendungssprache ausgewählt und das Kontrollkästchen
Storyboards verwenden aktiviert ist. Deaktivieren Sie die Kontrollkästchen
Dokumentbasierte Anwendung erstellen ,
Kerndaten verwenden , Komponententests einschließen und
UI-Tests einschließen .

Klicken Sie
abschließend erneut auf
Weiter , geben Sie den Speicherort für das Projekt an und klicken Sie auf
Erstellen .
Öffnen Sie nach dem
Erstellen des neuen Projekts
AppDelegate.swift und fügen Sie der Klasse die folgende Eigenschaft hinzu:
let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.squareLength)
Hier erstellen wir in der Menüleiste Statuselement (Anwendungssymbol) eine feste Länge, die für Benutzer sichtbar ist.
Dann müssen wir unser Bild diesem neuen Element in der Menüleiste zuweisen, damit wir unsere neue Anwendung unterscheiden können.
Gehen Sie im Projektnavigator zu Assets.xcassets,
laden Sie ein Bild hoch und ziehen Sie es in den Asset-Katalog.
Wählen Sie ein Bild aus und öffnen Sie den Attributinspektor. Ändern Sie die Option
Rendern als in
Vorlagenbild .

Wenn Sie ein eigenes Bild verwenden, stellen Sie sicher, dass das Bild schwarzweiß ist, und konfigurieren Sie es als
Vorlagenbild, damit das Symbol sowohl in der dunklen als auch in der hellen Menüleiste gut aussieht.
Gehen Sie zurück zu
AppDelegate.swift und fügen Sie den folgenden Code zu
applicationDidFinishLaunching (_ :) hinzu. if let button = statusItem.button { button.image = NSImage(named:NSImage.Name("StatusBarButtonImage")) button.action = #selector(printQuote(_:)) }
Hier weisen wir das Anwendungssymbol zu, das wir gerade zum Anwendungssymbol hinzugefügt haben, und weisen eine
Aktion zu, wenn wir darauf klicken.
Fügen Sie der Klasse die folgende Methode hinzu:
@objc func printQuote(_ sender: Any?) { let quoteText = "Never put off until tomorrow what you can do the day after tomorrow." let quoteAuthor = "Mark Twain" print("\(quoteText) — \(quoteAuthor)") }
Diese Methode druckt einfach das Zitat auf die Konsole.
Beachten Sie die
objc- Methodenrichtlinie. Auf diese Weise können Sie diese Methode als Antwort auf einen Schaltflächenklick verwenden.
Erstellen Sie die Anwendung und führen Sie sie aus. Die neue Anwendung wird in der Menüleiste angezeigt. Hurra!
Jedes Mal, wenn Sie auf das Symbol in der Menüleiste klicken, wird das berühmte Sprichwort von Mark Twain in der Xcode-Konsole angezeigt.
Wir verstecken das Hauptfenster und das Symbol im Dock
Es gibt ein paar kleine Dinge, die wir tun müssen, bevor wir uns direkt mit der Funktionalität befassen:
- Dock-Symbol löschen
- Entfernen Sie unnötiges Hauptfenster der Anwendung
Öffnen Sie die
Info.plist, um das Dock-Symbol zu entfernen. Fügen Sie einen neuen
UIElement- Schlüssel
(Application is Agent) hinzu und setzen Sie seinen Wert auf
YES .

Jetzt ist es an der Zeit, sich mit dem Hauptanwendungsfenster zu befassen.
- Öffnen Sie das Main.storyboard
- Wählen Sie Window Controller-Szene und löschen Sie sie
- View Controller Szene verlassen, wir werden es bald verwenden

Erstellen Sie die Anwendung und führen Sie sie aus. Jetzt hat die Anwendung nicht mehr sowohl das Hauptfenster als auch das unnötige Symbol im Dock. Großartig!
Menü zum Statuselement hinzufügen
Eine Antwort mit einem Klick reicht für eine ernsthafte Anwendung eindeutig nicht aus. Der einfachste Weg, Funktionen hinzuzufügen, ist das Hinzufügen eines Menüs. Fügen Sie diese Funktion am Ende von
AppDelegate hinzu .
func constructMenu() { let menu = NSMenu() menu.addItem(NSMenuItem(title: "Print Quote", action: #selector(AppDelegate.printQuote(_:)), keyEquivalent: "P")) menu.addItem(NSMenuItem.separator()) menu.addItem(NSMenuItem(title: "Quit Quotes", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q")) statusItem.menu = menu }
Fügen Sie diesen Aufruf am Ende von
applicationDidFinishLaunching (_ :) hinzu. constructMenu()
Wir erstellen
NSMenu , fügen 3 Instanzen von
NSMenuItem hinzu und legen dieses Menü als Anwendungssymbolmenü fest.
Einige wichtige Punkte:
- Der Titel des Menüelements ist der Text, der im Menü angezeigt wird. Ein guter Ort, um die Anwendung zu lokalisieren (falls erforderlich).
- Aktion ist wie die Aktion einer Schaltfläche oder eines anderen Steuerelements eine Methode, die aufgerufen wird, wenn der Benutzer auf einen Menüpunkt klickt
- keyEquivalent ist eine Tastenkombination, mit der Sie einen Menüpunkt auswählen können. Kleinbuchstaben verwenden Cmd als Modifikator und Kleinbuchstaben verwenden Cmd + Umschalt . Dies funktioniert nur, wenn sich die Anwendung ganz oben befindet und aktiv ist. In unserem Fall ist es erforderlich, dass das Menü oder ein anderes Fenster sichtbar ist, da unsere Anwendung kein Symbol im Dock hat
- separatorItem ist ein inaktiver Menüpunkt in Form einer grauen Linie zwischen anderen Elementen. Verwenden Sie es zum Gruppieren
- printQuote ist die Methode, die Sie bereits in AppDelegate definiert haben , und terminate ist die von NSApplication definierte Methode .
Starten Sie die Anwendung und Sie sehen ein Menü, indem Sie auf das Anwendungssymbol klicken.

Klicken Sie auf das Menü. Wenn Sie Angebot drucken auswählen, wird das Angebot in der Xcode-Konsole angezeigt, und
Angebote beenden beendet die Anwendung.
Fügen Sie ein Popup hinzu
Sie haben gesehen, wie einfach es ist, ein Menü aus dem Code hinzuzufügen, aber das Anzeigen eines Zitats in der Xcode-Konsole entspricht eindeutig nicht den Erwartungen der Benutzer an die Anwendung. Jetzt fügen wir einen einfachen Ansichts-Controller hinzu, um Anführungszeichen auf die richtige Weise anzuzeigen.
Gehen Sie zum Menü
Datei / Neu / Datei ... , wählen Sie die Vorlage
macOS / Source / Cocoa Class aus und klicken Sie auf
Weiter .

- Nennen Sie die Klasse QuotesViewController
- Machen Sie einen Erben von NSViewController
- Stellen Sie sicher, dass das Kontrollkästchen Auch XIB-Datei für Benutzeroberfläche erstellen nicht aktiviert ist
- Stellen Sie die Sprache auf Swift ein
Klicken Sie
abschließend erneut auf
Weiter , wählen Sie einen Speicherort für die Datei aus und klicken Sie auf
Erstellen .
Öffnen
Sie nun
Main.storyboard . Erweitern Sie
View Controller Scene und wählen Sie
View Controller-Instanz aus .
Wählen Sie zuerst den
Identitätsinspektor aus und ändern Sie die Klasse in
QuotesViewController. Setzen Sie dann die
Storyboard-ID auf
QuotesViewControllerFügen Sie nun den folgenden Code am Ende der Datei
QuotesViewController.swift hinzu :
extension QuotesViewController {
Was ist hier los:
- Wir bekommen einen Link zu Main.storyboard .
- Erstellen Sie eine Szenen-ID , die mit der oben installierten übereinstimmt.
- Erstellen Sie eine Instanz von QuotesViewController und geben Sie sie zurück.
Sie erstellen diese Methode, sodass jetzt jeder, der den
QuotesViewController verwendet, nicht mehr wissen muss, wie er erstellt wird. Es funktioniert einfach.
Beachten Sie den
fatalError in der
Guard- Anweisung. Es kann hilfreich sein, es oder
assertionFailure zu verwenden, damit Sie selbst und die anderen Mitglieder des Entwicklungsteams Bescheid wissen, wenn etwas in der Entwicklung schief geht.
Nun zurück zu
AppDelegate.swift . Fügen Sie eine neue Eigenschaft hinzu.
let popover = NSPopover()
Ersetzen Sie dann ein
pplicationDidFinishLaunching (_ :) durch den folgenden Code:
func applicationDidFinishLaunching(_ aNotification: Notification) { if let button = statusItem.button { button.image = NSImage(named:NSImage.Name("StatusBarButtonImage")) button.action = #selector(togglePopover(_:)) } popover.contentViewController = QuotesViewController.freshController() }
Sie haben die
Klickaktion geändert, um die Methode
togglePopover (_ :) aufzurufen , die wir etwas später schreiben werden. Anstatt ein Menü zu konfigurieren und hinzuzufügen, haben wir ein Popup-Fenster konfiguriert, in dem etwas von
QuotesViewController angezeigt wird .
Fügen Sie
AppDelegate die folgenden drei Methoden
hinzu :
@objc func togglePopover(_ sender: Any?) { if popover.isShown { closePopover(sender: sender) } else { showPopover(sender: sender) } } func showPopover(sender: Any?) { if let button = statusItem.button { popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY) } } func closePopover(sender: Any?) { popover.performClose(sender) }
showPopover () zeigt ein Popup. Sie geben nur an, woher es kommt, macOS positioniert es und zeichnet einen Pfeil, als würde er in der Menüleiste angezeigt.
closePopover () schließt nur das Popup, und
togglePopover () ist eine Methode, die das Popup je nach Status entweder
ein- oder
ausblendet .
Starten Sie die Anwendung und klicken Sie auf das entsprechende Symbol.

Alles ist in Ordnung, aber wo ist der Inhalt?
Wir implementieren den Quote View Controller
Zunächst benötigen Sie ein Modell zum Speichern von Anführungszeichen und Attributen. Gehen Sie zum Menü
Datei / Neu / Datei ... und wählen Sie die
Vorlage macOS / Quelle / Swift-Datei und dann
Weiter . Benennen Sie die Datei
Quote und klicken Sie auf
Create .
Öffnen Sie die Datei
Quote.swift und fügen Sie den folgenden Code hinzu:
struct Quote { let text: String let author: String static let all: [Quote] = [ Quote(text: "Never put off until tomorrow what you can do the day after tomorrow.", author: "Mark Twain"), Quote(text: "Efficiency is doing better what is already being done.", author: "Peter Drucker"), Quote(text: "To infinity and beyond!", author: "Buzz Lightyear"), Quote(text: "May the Force be with you.", author: "Han Solo"), Quote(text: "Simplicity is the ultimate sophistication", author: "Leonardo da Vinci"), Quote(text: "It's not just what it looks like and feels like. Design is how it works.", author: "Steve Jobs") ] } extension Quote: CustomStringConvertible { var description: String { return "\"\(text)\" — \(author)" } }
Hier definieren wir eine einfache Anführungszeichenstruktur und eine statische Eigenschaft, die alle Anführungszeichen zurückgibt. Da wir
Quote mit dem
CustomStringConvertible- Protokoll kompatibel
gemacht haben , können wir problemlos bequem formatierten Text erhalten.
Es gibt Fortschritte, aber wir brauchen noch Steuerelemente, um all dies anzuzeigen.
Fügen Sie Schnittstellenelemente hinzu
Öffnen Sie Main.storyboard und ziehen Sie 3 Tasten (Drucktaste) und Beschriftung (Mehrzeilige Beschriftung
) auf dem Ansichts-Controller heraus.
Positionieren Sie die Schaltflächen und Beschriftungen so, dass sie ungefähr so aussehen:

Befestigen Sie den linken Knopf mit einem Abstand von 20 am linken Rand und zentrieren Sie ihn vertikal.
Befestigen Sie den rechten Knopf mit einem Abstand von 20 am rechten Rand und zentrieren Sie ihn vertikal.
Befestigen Sie den unteren Knopf mit einem Abstand von 20 an der Unterkante und zentrieren Sie ihn horizontal.
Befestigen Sie den linken und rechten Rand der Markierung mit einem Abstand von 20 in vertikaler Mitte an den Schaltflächen.

Sie werden mehrere Layoutfehler sehen, da nicht genügend Informationen für das
automatische Layout vorhanden sind, um dies herauszufinden.
Setzen Sie die
Priorität für das
Umarmen horizontaler Inhalte auf 249, damit die Größe des Etiketts geändert werden kann.

Gehen Sie nun wie folgt vor:
- Setzen Sie das Bild mit der linken Schaltfläche auf NSGoLeftTemplate und löschen Sie den Titel
- Setzen Sie das Bild mit der rechten Schaltfläche auf NSGoRightTemplate und löschen Sie den Titel
- Setzen Sie den Titel der Schaltfläche unten auf Quit Quotes .
- Stellen Sie die Textausrichtung des Etiketts auf Mitte ein.
- Überprüfen Sie, ob der Zeilenumbruch am Etikett auf Zeilenumbruch eingestellt ist .
Öffnen
Sie nun
QuotesViewController.swift und fügen Sie der Implementierung der
QuotesViewController- Klasse den folgenden Code
hinzu :
@IBOutlet var textLabel: NSTextField!
Fügen Sie diese Erweiterung der Klassenimplementierung hinzu. In
QuotesViewController.swift gibt es jetzt zwei Klassenerweiterungen.
Wir haben gerade eine
Steckdose für das Etikett hinzugefügt, mit dem wir Anführungszeichen anzeigen, und drei Stub-Methoden, die wir mit den Schaltflächen verbinden.
Verbinden des Codes mit Interface Builder
Hinweis: Xcode hat Kreise links von Ihrem Code platziert - neben den Schlüsselwörtern
IBAction und
IBOutlet .

Wir werden sie verwenden, um den Code mit der Benutzeroberfläche zu verbinden.
Klicken Sie bei
gedrückter Alt- Taste im
Projektnavigator auf
Main.storyboard . Daher wird das
Storyboard im
Assistenten-Editor rechts und der Code links geöffnet.
Ziehen Sie den Kreis links von
textLabel auf die Beschriftung im
Interface Builder . Kombinieren Sie auf die gleiche Weise die
vorherigen ,
nächsten und
Beendigungsmethoden mit den Schaltflächen links, rechts und unten.

Starten Sie Ihre Anwendung.

Wir haben die Standard-Popup-Größe verwendet. Wenn Sie ein größeres oder kleineres Popup möchten, ändern Sie einfach die Größe im
Storyboard .
Schreiben eines Codes für die Schaltflächen
Wenn Sie den
Assistenten-Editor noch nicht ausgeblendet haben, klicken Sie auf
Befehlsrückgabe oder
Ansicht> Standardeditor> Standardeditor anzeigenÖffnen Sie
QuotesViewController.swift und fügen Sie der
Klassenimplementierung die folgenden Eigenschaften hinzu:
let quotes = Quote.all var currentQuoteIndex: Int = 0 { didSet { updateQuote() } }
Die
Anführungszeichen- Eigenschaft enthält alle Anführungszeichen, und
currentQuoteIndex ist der Index des
Angebots , das derzeit angezeigt wird.
CurrentQuoteIndex verfügt außerdem über einen
Eigenschaftsbeobachter, mit dem der Inhalt des Etiketts mit einem neuen Anführungszeichen aktualisiert werden kann, wenn sich der Index ändert.
Fügen Sie nun die folgenden Methoden hinzu:
override func viewDidLoad() { super.viewDidLoad() currentQuoteIndex = 0 } func updateQuote() { textLabel.stringValue = String(describing: quotes[currentQuoteIndex]) }
Wenn die Ansicht geladen wird, setzen wir den Anführungszeichenindex auf 0, was wiederum zu einer Aktualisierung der Schnittstelle führt.
updateQuote () aktualisiert einfach die
Textbezeichnung , um ein Zitat anzuzeigen. entsprechender
currentQuoteIndex .
Aktualisieren Sie diese Methoden abschließend mit dem folgenden Code:
@IBAction func previous(_ sender: NSButton) { currentQuoteIndex = (currentQuoteIndex - 1 + quotes.count) % quotes.count } @IBAction func next(_ sender: NSButton) { currentQuoteIndex = (currentQuoteIndex + 1) % quotes.count } @IBAction func quit(_ sender: NSButton) { NSApplication.shared.terminate(sender) }
Die Methoden
next () und
previous () durchlaufen alle Zitate.
Beenden schließt die Anwendung.
Starten Sie die App:

Ereignisüberwachung
Es gibt noch eine Sache, die Benutzer von unserer Anwendung erwarten - das Popup-Fenster auszublenden, wenn der Benutzer irgendwo außerhalb darauf klickt. Dazu benötigen wir einen Mechanismus namens
macOS global event monitor .
Erstellen Sie eine neue Swift-Datei, nennen Sie sie
EventMonitor und ersetzen Sie ihren Inhalt durch den folgenden Code:
import Cocoa public class EventMonitor { private var monitor: Any? private let mask: NSEvent.EventTypeMask private let handler: (NSEvent?) -> Void public init(mask: NSEvent.EventTypeMask, handler: @escaping (NSEvent?) -> Void) { self.mask = mask self.handler = handler } deinit { stop() } public func start() { monitor = NSEvent.addGlobalMonitorForEvents(matching: mask, handler: handler) } public func stop() { if monitor != nil { NSEvent.removeMonitor(monitor!) monitor = nil } } }
Beim Initialisieren einer Instanz dieser Klasse übergeben wir ihr eine Ereignismaske, die wir abhören werden (z. B. Tastenanschläge, Mausrad-Bildlauf usw.), und einen Ereignishandler.
Wenn wir mit dem Abhören
beginnen möchten, ruft
start () addGlobalMonitorForEventsMatchingMask (_: handler :) auf , das das zu speichernde Objekt zurückgibt. Sobald das in der Maske enthaltene Ereignis eintritt, ruft das System Ihren Handler auf.
Um die Überwachung von Ereignissen zu stoppen, wird
removeMonitor () in
stop () aufgerufen und wir löschen das Objekt, indem wir es auf nil setzen.
Wir müssen nur noch
start () und
stop () zum richtigen Zeitpunkt aufrufen. Die Klasse ruft auch
stop () auf dem Deinitializer auf, um zu bereinigen.
Event Monitor verbinden
Öffnen Sie
AppDelegate.swift ein letztes Mal und fügen Sie eine neue Eigenschaft hinzu:
var eventMonitor: EventMonitor?
Fügen Sie dann diesen Code hinzu, um den
Ereignismonitor am Ende von
applicationDidFinishLaunching (_ :) zu konfigurieren.
eventMonitor = EventMonitor(mask: [.leftMouseDown, .rightMouseDown]) { [weak self] event in if let strongSelf = self, strongSelf.popover.isShown { strongSelf.closePopover(sender: event) } }
Dies informiert Ihre Anwendung, wenn Sie auf die linke oder rechte Schaltfläche klicken. Bitte beachten Sie: Der Handler wird nicht als Reaktion auf Mausklicks in Ihrer Anwendung aufgerufen. Aus diesem Grund wird das Popup nicht geschlossen, während Sie darauf klicken.
Wir verwenden einen
schwachen Bezug zu sich
selbst , um die Gefahr eines Zyklus starker Verbindungen zwischen
AppDelegate und
EventMonitor zu vermeiden.
Fügen Sie am Ende der
showPopover (_ :) -Methode den folgenden Code hinzu:
eventMonitor?.start()
Hier beginnen wir mit der Überwachung von Ereignissen, wenn ein Popup-Fenster angezeigt wird.
Fügen Sie nun den Code am Ende der Methode
closePopover (_ :) hinzu :
eventMonitor?.stop()
Hier beenden wir die Überwachung, wenn das Popup geschlossen wird.
Die Bewerbung ist fertig!
Fazit
Hier finden Sie den vollständigen Code für dieses Projekt.
Sie haben gelernt, wie Sie das Menü und das Popup in der Anwendung in der Menüleiste einstellen. Warum nicht mit mehreren Tags oder formatiertem Text experimentieren, um die Anführungszeichen besser sehen zu können? Oder ein Backend anschließen, um Angebote aus dem Internet zu erhalten? Oder möchten Sie mit der Tastatur zwischen Anführungszeichen navigieren?
Ein guter Ort zum Recherchieren ist die offizielle Dokumentation:
NSMenu ,
NSPopover und
NSStatusItem .