ã¡ãã¥ãŒããŒã§ãã¹ããããã¢ããªã±ãŒã·ã§ã³ã¯ãmacOSãŠãŒã¶ãŒã«é·ãéç¥ãããŠããŸãã ãããã®ã¢ããªã±ãŒã·ã§ã³ã«ã¯ããéåžžãã®éšåããããã®ãšãã¡ãã¥ãŒããŒã«ã®ã¿ãããã®ããããŸãã
ãã®ã¬ã€ãã§ã¯ãæåãªäººããã®åŒçšããããã¢ãããŠã£ã³ããŠã«è¡šç€ºããã¢ããªã±ãŒã·ã§ã³ãäœæããŸãã ãã®ã¢ããªã±ãŒã·ã§ã³ãäœæããéçšã§ã次ã®ããšãåŠã³ãŸãã
- ã¡ãã¥ãŒããŒã§ã¢ããªã±ãŒã·ã§ã³ã¢ã€ã³ã³ãå²ãåœãŠãŸã
- ã¢ããªã±ãŒã·ã§ã³ãã¡ãã¥ãŒããŒã§ã®ã¿ãã¹ããã
- ã«ã¹ã¿ã ã¡ãã¥ãŒãè¿œå
- ã€ãã³ãã¢ãã¿ãªã³ã°ã䜿çšããŠããŠãŒã¶ãŒã®èŠæ±æã«ãããã¢ãããŠã£ã³ããŠã衚瀺ããå¿
èŠã«å¿ããŠé衚瀺ã«ããŸã
泚ïŒãã®ã¬ã€ãã¯ãSwiftãšmacOSã«ç²ŸéããŠããããšãåæãšããŠããŸãã
ã¯ããã«
Xcodeãèµ·åããŸãã 次ã«ã
ãã¡ã€ã«/æ°èŠ/ãããžã§ã¯ã...ã¡ãã¥ãŒã§ã
macOS /ã¢ããªã±ãŒã·ã§ã³/ Cocoa Appãã³ãã¬ãŒããéžæãã
次ãžãã¯ãªãã¯ããŸãã
次ã®ç»é¢ã§ã
補ååãšããŠQuotesãšå
¥åãã
çµç¹åãš
çµç¹èå¥åãéžæããŸãã 次ã«ãã¢ããªã±ãŒã·ã§ã³èšèªãšããŠSwiftãéžæããã[
ã¹ããŒãªãŒããŒãã䜿çš]ãã§ãã¯ããã¯ã¹ããªã³ã«ãªã£ãŠããããšã確èªããŸãã [
ããã¥ã¡ã³ãããŒã¹ã®ã¢ããªã±ãŒã·ã§ã³ã®äœæ] ã[
ã³ã¢ããŒã¿ã®äœ¿çš] ã[
ãŠããããã¹ãã
å«ãã]ã[UIãã¹ãã
å«ãã]ãã§ãã¯ããã¯ã¹ããªãã«ã
ãŸã ã

æåŸã«ãããäžåºŠ[
次㞠]ãã¯ãªãã¯ãããããžã§ã¯ããä¿åããå Žæãæå®ããŠã[
äœæ ]ãã¯ãªãã¯ã
ãŸã ã
æ°ãããããžã§ã¯ããäœæããããã
AppDelegate.swiftãéãã次ã®ããããã£ãã¯ã©ã¹ã«è¿œå ããŸãã
let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.squareLength)
ããã§ã¯ãã¡ãã¥ãŒããŒã®ã¹ããŒã¿ã¹ã¢ã€ãã ïŒã¢ããªã±ãŒã·ã§ã³ã¢ã€ã³ã³ïŒã«ããŠãŒã¶ãŒã«è¡šç€ºãããåºå®é·ãäœæããŸãã
次ã«ãæ°ããã¢ããªã±ãŒã·ã§ã³ãåºå¥ã§ããããã«ãã¡ãã¥ãŒããŒã®ãã®æ°ããã¢ã€ãã ã«ç»åãå²ãåœãŠãå¿
èŠããããŸãã
ãããžã§ã¯ãããã²ãŒã¿ã§ãAssets.xcassetsã«ç§»åã
ãåçã
ã¢ããããŒãããŠãè³ç£ã«ã¿ãã°ã«ãã©ãã°ããŸãã
ç»åãéžæããŠãå±æ§ã€ã³ã¹ãã¯ã¿ãŒãéããŸãã
Render Asãªãã·ã§ã³ã
Template Imageã«å€æŽããŸãã

ç¬èªã®ç»åã䜿çšããå Žåã¯ãç»åãçœé»ã§ããããšã確èªãã
ãã³ãã¬ãŒãã¡ãã¥ãŒãšããŠèšå®ããŠãæãã¡ãã¥ãŒããŒãšæããã¡ãã¥ãŒããŒã®äž¡æ¹ã§ã¢ã€ã³ã³ããããã«èŠããããã«ããŸãã
AppDelegate.swiftã«æ»ãã次ã®ã³ãŒãã
applicationDidFinishLaunchingïŒ_ :)ã«è¿œå ããŸã
if let button = statusItem.button { button.image = NSImage(named:NSImage.Name("StatusBarButtonImage")) button.action = #selector(printQuote(_:)) }
ããã§ãã¢ããªã±ãŒã·ã§ã³ã¢ã€ã³ã³ã«è¿œå ããã°ããã®ã¢ããªã±ãŒã·ã§ã³ã¢ã€ã³ã³ãå²ãåœãŠãã¯ãªãã¯ãããšãã«
ã¢ã¯ã·ã§ã³ãå²ãåœãŠãŸãã
次ã®ã¡ãœãããã¯ã©ã¹ã«è¿œå ããŸãã
@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)") }
ãã®ã¡ãœããã¯ãåã«åŒçšãã³ã³ãœãŒã«ã«åºåããŸãã
objcã¡ãœãã
ãã£ã¬ã¯ãã£ãã«æ³šæããŠãã ããã ããã«ããããã¿ã³ã¯ãªãã¯ãžã®å¿çãšããŠãã®ã¡ââãœããã䜿çšã§ããŸãã
ã¢ããªã±ãŒã·ã§ã³ããã«ãããŠå®è¡ãããšãã¡ãã¥ãŒããŒã«æ°ããã¢ããªã±ãŒã·ã§ã³ã衚瀺ãããŸãã ãã£ãïŒ
ã¡ãã¥ãŒããŒã®ã¢ã€ã³ã³ãã¯ãªãã¯ãããã³ã«ãããŒã¯ããŠã§ã€ã³ã®æåãªæ ŒèšãXcodeã³ã³ãœãŒã«ã«è¡šç€ºãããŸãã
ã¡ã€ã³ãŠã£ã³ããŠãšããã¯ã®ã¢ã€ã³ã³ãé衚瀺ã«ããŸã
æ©èœãçŽæ¥æ±ãåã«è¡ãå¿
èŠã®ããå°ããªããšãããã€ããããŸãã
- ããã¯ã¢ã€ã³ã³ãåé€
- äžèŠãªã¢ããªã±ãŒã·ã§ã³ã®ã¡ã€ã³ãŠã£ã³ããŠãåé€ãã
ããã¯ã¢ã€ã³ã³ãåé€ããã«ã¯ã
Info.plistãéã
ãŸã ã æ°ãã
Application is agentïŒUIElementïŒããŒãè¿œå ãããã®å€ã
YESã«èšå®ããŸãã

ããã§ãã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³ãŠã£ã³ããŠãåŠçããŸãã
- Main.storyboardãéã
- Window Controllerã·ãŒã³ãéžæããŠåé€ããŸã
- ãã¥ãŒã³ã³ãããŒã©ãŒã·ãŒã³ã®äŒæãããã«äœ¿çšããŸã

ã¢ããªã±ãŒã·ã§ã³ããã«ãããŠå®è¡ããŸãã ããã§ãã¢ããªã±ãŒã·ã§ã³ã®ã¡ã€ã³ãŠã£ã³ããŠãšäžèŠãªã¢ã€ã³ã³ã®äž¡æ¹ãããã¯ã«ãããŸããã ãããïŒ
ã¹ããŒã¿ã¹ã¢ã€ãã ã«ã¡ãã¥ãŒãè¿œå
é倧ãªã¢ããªã±ãŒã·ã§ã³ã«ã¯ãã·ã³ã°ã«ã¯ãªãã¯å¿çã ãã§ã¯æããã«äžååã§ãã æ©èœãè¿œå ããæãç°¡åãªæ¹æ³ã¯ãã¡ãã¥ãŒãè¿œå ããããšã§ãã
AppDelegateã®æåŸã«ãã®é¢æ°ãè¿œå ããŸãã
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 }
ãããŠã
applicationDidFinishLaunchingïŒ_ :)ã®æåŸã«ãã®åŒã³åºããè¿œå ããŸã
constructMenu()
NSMenuãäœæãã
NSMenuItemã® 3ã€ã®ã€ã³ã¹ã¿ã³ã¹ã
ããã«è¿œå ãããã®ã¡ãã¥ãŒãã¢ããªã±ãŒã·ã§ã³ã¢ã€ã³ã³ã¡ãã¥ãŒãšããŠèšå®ããŸãã
ããã€ãã®éèŠãªãã€ã³ãïŒ
- ã¡ãã¥ãŒé
ç®ã®ã¿ã€ãã«ã¯ãã¡ãã¥ãŒã«è¡šç€ºãããããã¹ãã§ãã ã¢ããªã±ãŒã·ã§ã³ãããŒã«ã©ã€ãºããã®ã«é©ããå ŽæïŒå¿
èŠãªå ŽåïŒã
- action ã¯ããã¿ã³ãŸãã¯ä»ã®ã³ã³ãããŒã«ã®ã¢ã¯ã·ã§ã³ãšåæ§ã«ããŠãŒã¶ãŒãã¡ãã¥ãŒé
ç®ãã¯ãªãã¯ãããšãã«åŒã³åºãããã¡ãœããã§ã
- keyEquivalentã¯ãã¡ãã¥ãŒé
ç®ãéžæããããã«äœ¿çšã§ããããŒããŒãã·ã§ãŒãã«ããã§ãã å°æåã¯ä¿®é£ŸåãšããŠCmdã䜿çšããå°æåã¯Cmd + Shiftã䜿çšããŸã ã ããã¯ãã¢ããªã±ãŒã·ã§ã³ãæäžäœã«ãããã¢ã¯ãã£ããªå Žåã«ã®ã¿æ©èœããŸãã ãã®å Žåãã¢ããªã±ãŒã·ã§ã³ã«ã¯ããã¯ã«ã¢ã€ã³ã³ããªããããã¡ãã¥ãŒãŸãã¯ä»ã®ãŠã£ã³ããŠã衚瀺ãããŠããå¿
èŠããããŸã
- separatorItemã¯ãä»ã®èŠçŽ ã®éã®ç°è²ã®ç·ã®åœ¢ã®éã¢ã¯ãã£ããªã¡ãã¥ãŒé
ç®ã§ãã ã°ã«ãŒãã«äœ¿çšãã
- printQuoteã¯AppDelegateã§æ¢ã«å®çŸ©ããã¡ãœããã§ããã terminateã¯NSApplicationã§å®çŸ©ãããã¡ãœããã§ãã
ã¢ããªã±ãŒã·ã§ã³ãèµ·åãããšãã¢ããªã±ãŒã·ã§ã³ã¢ã€ã³ã³ãã¯ãªãã¯ããŠã¡ãã¥ãŒã衚瀺ãããŸãã

ã¡ãã¥ãŒãã¯ãªãã¯ããŠã¿ãŠãã ãã-
èŠç©ã®å°å·ãéžæãããšãXcodeã³ã³ãœãŒã«ã«
èŠç©ã衚瀺ãããèŠç©ãçµäºãããšã¢ããªã±ãŒã·ã§ã³ãçµäºããŸãã
ãããã¢ãããè¿œå ãã
ã³ãŒãããã¡ãã¥ãŒãè¿œå ããã®ãã©ãã»ã©ç°¡åããèŠãŸããããXcodeã³ã³ãœãŒã«ã«åŒçšç¬Šã衚瀺ããããšã¯ããŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ã«æåŸ
ãããã®ãšã¯æããã«ç°ãªããŸãã 次ã«ãã·ã³ãã«ãªView Controllerãè¿œå ããŠãæ£ããæ¹æ³ã§èŠç©ããã衚瀺ããŸãã
ãã¡ã€ã«/æ°èŠ/ãã¡ã€ã«...ã¡ãã¥ãŒã«ç§»åãã
macOS /ãœãŒã¹/ Cocoa Classãã³ãã¬ãŒããéžæããŠã
次ãžãã¯ãªãã¯ããŸãã

- ã¯ã©ã¹ã«QuotesViewControllerãšããååãä»ããŸã
- NSViewControllerã®çžç¶äººãäœããŸã
- [ ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã®XIBãã¡ã€ã«ãäœæãã]ãã§ãã¯ããã¯ã¹ããªãã«ãªã£ãŠããããšã確èªããŸãã
- èšèªãSwiftã«èšå®ããŸã
æåŸã«ãããäžåºŠ[
次㞠]ãã¯ãªãã¯ãããã¡ã€ã«ãä¿åããå ŽæãéžæããŠã[
äœæ ]ãã¯ãªãã¯ã
ãŸã ã
Main.storyboardãéã
ãŸã ã [
View Controller Scene]ãå±éã ã[
View Controller instance]ãéžæã
ãŸã ã

æåã«
Identity Inspectorãéžæããã¯ã©ã¹ã
QuotesViewControllerã«å€æŽããŠããã
ã¹ããŒãªãŒããŒãIDã
QuotesViewControllerã«èšå®ã
ãŸã次ã«ã
QuotesViewController.swiftãã¡ã€ã«ã®æåŸã«æ¬¡ã®ã³ãŒããè¿œå ããŸãã
extension QuotesViewController {
ããã§äœãèµ·ãã£ãŠããŸããïŒ
- Main.storyboardãžã®ãªã³ã¯ãååŸããŸãã
- çŽåã«ã€ã³ã¹ããŒã«ãããã®ãšäžèŽããã·ãŒã³èå¥åãäœæããŸãã
- QuotesViewControllerã®ã€ã³ã¹ã¿ã³ã¹ãäœæããŠè¿ããŸãã
ãã®ã¡ãœãããäœæããã®ã§ã
QuotesViewControllerã䜿çšãããã¹ãŠã®äººããã®äœææ¹æ³ãç¥ãå¿
èŠããªããªããŸããã ããã ãã§åäœããŸãã
guardã¹ããŒãã¡ã³ãå
ã®
fatalErrorã«æ³šæããŠãã ããã éçºäžã«äœãåé¡ãçºçããå Žåã«ãããªãèªèº«ãšéçºããŒã ã®ä»ã®ã¡ã³ããŒãç¥ãããšãã§ããããã«ãããã䜿çšããã
assertionFailureããã®ã¯è¯ãããšã§ãã
AppDelegate.swiftã«æ»ããŸãã æ°ããããããã£ãè¿œå ããŸãã
let popover = NSPopover()
次ã«ã
pplicationDidFinishLaunchingïŒ_ :)ã次ã®ã³ãŒãã«çœ®ãæããŸãã
func applicationDidFinishLaunching(_ aNotification: Notification) { if let button = statusItem.button { button.image = NSImage(named:NSImage.Name("StatusBarButtonImage")) button.action = #selector(togglePopover(_:)) } popover.contentViewController = QuotesViewController.freshController() }
ã¯ãªãã¯ã¢ã¯ã·ã§ã³ãå€æŽããŠã
togglePopoverïŒ_ :)ã¡ãœãããåŒã³åºããŸãããããã«ã€ããŠã¯ãåŸã§èª¬æããŸãã ãŸããã¡ãã¥ãŒãã«ã¹ã¿ãã€ãºããŠè¿œå ãã代ããã«ã
QuotesViewControllerããäœãã衚瀺ãããããã¢ãããŠã£ã³ããŠãæ§æã
ãŸãã ã
次ã®3ã€ã®ã¡ãœããã
AppDelegateã«è¿œå ããŸãã
@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ïŒïŒã¯ãããã¢ããã衚瀺ããŸãã ããªãã¯ãããã©ãããæ¥ããã瀺ãã ãã§ãmacOSã¯ãããé
眮ããã¡ãã¥ãŒããŒããçŸãããã®ããã«ç¢å°ãæããŸãã
closePopoverïŒïŒã¯åã«ãããã¢ãããéãã
togglePopoverïŒïŒã¯ç¶æ
ã«å¿ããŠãããã¢ããã衚瀺ãŸãã¯é衚瀺ã«ããã¡ãœããã§ãã
ã¢ããªã±ãŒã·ã§ã³ãèµ·åãããã®ã¢ã€ã³ã³ãã¯ãªãã¯ããŸãã

ãã¹ãŠã¯åé¡ãããŸããããã³ã³ãã³ãã¯ã©ãã«ãããŸããïŒ
Quote View Controllerãå®è£
ããŸã
ãŸããåŒçšç¬Šãšå±æ§ãä¿åããããã®ã¢ãã«ãå¿
èŠã§ãã
ãã¡ã€ã«/æ°èŠ/ãã¡ã€ã«...ã¡ãã¥ãŒã«ç§»åãã
macOS /ãœãŒã¹/ Swiftãã¡ã€ã«ãã³ãã¬ãŒããéžæãã
次ãžãéžæããŸãã ãã¡ã€ã«ã«
Quoteãšããååãä»ããŠã[
äœæ ]ãã¯ãªãã¯ã
ãŸã ã
Quote.swiftãã¡ã€ã«ãéãã次ã®ã³ãŒããè¿œå ããŸãã
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)" } }
ããã§ã¯ãåçŽãªåŒçšæ§é ãšããã¹ãŠã®åŒçšãè¿ãéçããããã£ãå®çŸ©ããŸãã
CustomStringConvertibleãããã³ã«ã«æºæ ãã
Quoteãäœæããããã䟿å©ãªãã©ãŒãããã®ããã¹ããç°¡åã«ååŸã§ããŸãã
é²æ©ã¯ãããŸãããããããã¹ãŠè¡šç€ºããã«ã¯ã³ã³ãããŒã«ãå¿
èŠã§ãã
ã€ã³ã¿ãŒãã§ã€ã¹èŠçŽ ãè¿œå ãã
Main.storyboardãéããView Controllerã§3ã€ã®ãã¿ã³ïŒ
ããã·ã¥ãã¿ã³ ïŒãšã©ãã«ïŒ
ãã«ãã©ã€ã³ã©ãã«ïŒãåŒãåºããŸãã
ãã¿ã³ãšã©ãã«ã次ã®ããã«é
眮ããŸãã

20ã®ã®ã£ãããšåçŽæ¹åã®äžå€®ã«å·Šãã¿ã³ã巊端ã«åãä»ããŸãã
20ã®ã®ã£ããã§åçŽã«äžå€®ã«å³ãã¿ã³ãå³ç«¯ã«åãä»ããŸãã
20ã®ã®ã£ããã§æ°Žå¹³æ¹åã®äžå€®ã«äžéšãã¿ã³ãäžç«¯ã«åãä»ããŸãã
ã©ãã«ã®å·Šç«¯ãšå³ç«¯ã20ã®ééã§ãã¿ã³ã«åãä»ããåçŽæ¹åã®äžå€®ã«é
眮ããŸãã
èªåã¬ã€ã¢ãŠããç解ããã®ã«ååãªæ
å ±ããªããããããã€ãã®ã¬ã€ã¢ãŠããšã©ãŒã衚瀺ãããŸãã
ã©ãã«ã®ãµã€ãºãå€æŽã§ããããã«ã
æ°Žå¹³ã³ã³ãã³ãã®ãã°ã®åªå
床ã249ã«èšå®ããŸãã

次ã®æé ãå®è¡ããŸãã
- å·Šãã¿ã³ã®ç»åãNSGoLeftTemplateã«èšå®ãã ã¿ã€ãã«ãã¯ãªã¢ããŸã
- å³ãã¿ã³ã®ç»åãNSGoRightTemplateã«èšå®ãã ã¿ã€ãã«ãã¯ãªã¢ããŸã
- Quit Quotesã§äžã®ãã¿ã³ã®ã¿ã€ãã«ãèšå®ããŸãã
- ã©ãã«ã®ããã¹ãã®é
眮ãäžå€®ã«èšå®ããŸã ã
- ã©ãã«ã®æ¹è¡ãã¯ãŒãã©ããã«èšå®ãããŠããããšã確èªããŸã ã
QuotesViewController.swiftãéãã
QuotesViewControllerã¯ã©ã¹ã®å®è£
ã«æ¬¡ã®ã³ãŒããè¿œå ããŸãã
@IBOutlet var textLabel: NSTextField!
ãã®æ¡åŒµæ©èœãã¯ã©ã¹å®è£
ã«è¿œå ããŸãã
QuotesViewController.swiftã«ã¯ã 2ã€ã®ã¯ã©ã¹æ¡åŒµããããŸãã
åŒçšç¬Šã®è¡šç€ºã«äœ¿çšããã©ãã«ã®
ã¢ãŠãã¬ãããšããã¿ã³ã«æ¥ç¶ãã3ã€ã®ã¹ã¿ãã¡ãœãããè¿œå ããŸããã
Interface Builderã§ã³ãŒããæ¥ç¶ãã
泚ïŒXcodeã¯ãã³ãŒãã®å·ŠåŽã
ã€ãŸãIBActionããã³
IBOutletããŒã¯ãŒãã®é£ã«åãé
眮ããŠããŸãã

ãããã䜿çšããŠãã³ãŒããUIã«æ¥ç¶ããŸãã
AltããŒãæŒããªããã
ãããžã§ã¯ãããã²ãŒã¿ãŒã® Main.storyboardãã¯ãªãã¯ããŸãã ãããã£ãŠã
ã¹ããŒãªãŒããŒãã¯å³åŽã®
ã¢ã·ã¹ã¿ã³ããšãã£ã¿ãŒã§éããã³ãŒãã¯å·ŠåŽã«éããŸãã
textLabelã®å·Šã«ããåãã
ã€ã³ã¿ãŒãã§ã€ã¹ãã«ããŒã®ã©ãã«ã«ãã©ãã°ã
ãŸã ã åæ§ã«ã
previous ã
nextã quitã¡ãœãããããããå·Šãå³ãäžã®ãã¿ã³ãšçµã¿åãããŸãã

ã¢ããªã±ãŒã·ã§ã³ãèµ·åããŸãã

ããã©ã«ãã®ãããã¢ãããµã€ãºã䜿çšããŸããã 倧ãããããã¢ãããŸãã¯å°ãããããã¢ãããå¿
èŠãªå Žåã¯ã
ã¹ããŒãªãŒããŒãã§ãµã€ãºãå€æŽããŠãã ããã
ãã¿ã³ã®ã³ãŒããæžã
ã¢ã·ã¹ã¿ã³ããšãã£ã¿ãŒããŸã é衚瀺ã«ããŠããªãå Žåã¯ã[
Cmd-Return ]ãŸãã¯[
ãã¥ãŒ]> [æšæºãšãã£ã¿ãŒ]> [æšæºãšãã£ã¿ãŒã衚瀺 ]ãã¯ãªãã¯ããŸã
QuotesViewController.swiftãéãã次ã®ããããã£ãã¯ã©ã¹å®è£
ã«è¿œå ããŸãã
let quotes = Quote.all var currentQuoteIndex: Int = 0 { didSet { updateQuote() } }
quotesããããã£ã«ã¯ãã¹ãŠã®åŒçšç¬Šãå«ãŸãã
currentQuoteIndexã¯çŸåšè¡šç€ºãããŠããåŒçšç¬Šã®ã€ã³ããã¯ã¹ã§ãã
CurrentQuoteIndexã«ã¯ãã€ã³ããã¯ã¹ãå€æŽããããšãã«ã©ãã«ã®å
容ãæ°ããåŒçšã§æŽæ°ãã
ããããã£ãªãã¶ãŒããŒããããŸãã
次ã®ã¡ãœãããè¿œå ããŸãã
override func viewDidLoad() { super.viewDidLoad() currentQuoteIndex = 0 } func updateQuote() { textLabel.stringValue = String(describing: quotes[currentQuoteIndex]) }
ãã¥ãŒãèªã¿èŸŒãŸãããšãåŒçšã€ã³ããã¯ã¹ã0ã«èšå®ããŸããããã«ãããã€ã³ã¿ãŒãã§ãŒã¹ãæŽæ°ãããŸãã
updateQuoteïŒïŒã¯ãããã¹ãã©ãã«ãæŽæ°ããŠåŒçšã衚瀺ããã ãã§ãã
currentQuoteIndexã«å¯Ÿå¿ã
ãŸã ã
æåŸã«ããããã®ã¡ãœããã次ã®ã³ãŒãã§æŽæ°ããŸãã
@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) }
nextïŒïŒããã³
previousïŒïŒã¡ãœããã¯ããã¹ãŠã®åŒçšã埪ç°ããŸãã
quitã¯ãã¢ããªã±ãŒã·ã§ã³
ãéããŸãã
ã¢ããªã±ãŒã·ã§ã³ãèµ·åããŸãã

ã€ãã³ãç£èŠ
ãŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ã«æåŸ
ãããã1ã€ã®ããšããããŸãããŠãŒã¶ãŒããããã¢ãããŠã£ã³ããŠã®å€åŽãã¯ãªãã¯ãããšãããã¢ãããŠã£ã³ããŠãé衚瀺ã«ããããšã§ãã ãããè¡ãã«ã¯ã
macOS global event monitorãšåŒã°ããã¡ã«ããºã ãå¿
èŠã§ãã
æ°ããSwiftãã¡ã€ã«ãäœæããããã
EventMonitorãš
åŒã³ ããã®å
容ã次ã®ã³ãŒãã«çœ®ãæããŸãã
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 } } }
ãã®ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãåæåãããšãã«ããªãã¹ã³ããã€ãã³ããã¹ã¯ïŒããŒã¹ãããŒã¯ãããŠã¹ãã€ãŒã«ã®ã¹ã¯ããŒã«ãªã©ïŒãšã€ãã³ããã³ãã©ãŒãæž¡ããŸãã
ãªã¹ãã³ã°ãéå§ããæºåãã§ãããã
startïŒïŒã
addGlobalMonitorForEventsMatchingMaskïŒ_ïŒhandler :)ãåŒã³åºããä¿åããŠãããªããžã§ã¯ããè¿ããŸãã ãã¹ã¯ã«å«ãŸããã€ãã³ããçºçãããšããã«ãã·ã¹ãã ã¯ãã³ãã©ãŒãåŒã³åºããŸãã
ã€ãã³ãã®ç£èŠãåæ¢ããã«ã¯ã
stopïŒïŒã§
removeMonitor ïŒïŒãåŒã³åºãããnilã«
èšå®ããŠãªããžã§ã¯ããåé€ããŸãã
æ®ã£ãŠããã®ã¯ãé©åãªã¿ã€ãã³ã°ã§
startïŒïŒãš
stopïŒïŒãåŒã³åºãããšã§ãã ãŸããã¯ã©ã¹ã¯ãã¯ãªãŒã³ã¢ããããããã«ãã€ãã·ã£ã©ã€ã¶ãŒã§
stopïŒïŒãåŒã³åºããŸãã
ã€ãã³ãã¢ãã¿ãŒã®æ¥ç¶
æåŸã«
AppDelegate.swiftãéããæ°ããããããã£ãè¿œå ããŸãã
var eventMonitor: EventMonitor?
次ã«ããã®ã³ãŒããè¿œå ããŠã
applicationDidFinishLaunchingã®æåŸã«
ã€ãã³ãã¢ãã¿ãŒãæ§æã
ãŸãïŒ_ :) eventMonitor = EventMonitor(mask: [.leftMouseDown, .rightMouseDown]) { [weak self] event in if let strongSelf = self, strongSelf.popover.isShown { strongSelf.closePopover(sender: event) } }
å·ŠãŸãã¯å³ã®ãã¿ã³ãã¯ãªãã¯ãããšãã¢ããªã±ãŒã·ã§ã³ã«éç¥ãããŸãã 泚ïŒã¢ããªã±ãŒã·ã§ã³å
ã§ã®ããŠã¹ã¯ãªãã¯ã«å¿çããŠãã³ãã©ãŒã¯åŒã³åºãããŸããã ãããããããã¢ãããã¯ãªãã¯ããŠãéããªãçç±ã§ãã
AppDelegateãš
EventMonitoréã®åŒ·åãªãªã³ã¯ã«ãŒãã®å±éºãåé¿ããããã«ã
匱ã èªå·±åç
§ã䜿çšããŸãã
showPopoverïŒ_ :)ã¡ãœããã®æåŸã«æ¬¡ã®ã³ãŒããè¿œå ããŸãã
eventMonitor?.start()
ããã§ã¯ããããã¢ãããŠã£ã³ããŠã衚瀺ããããšãã«ã€ãã³ãã®ç£èŠãéå§ããŸãã
次ã«ã
closePopoverïŒ_ :)ã¡ãœããã®æåŸã«ã³ãŒããè¿œå ããŸãã
eventMonitor?.stop()
ããã§ããããã¢ãããéãããç£èŠãçµäºããŸãã
ã¢ããªã±ãŒã·ã§ã³ã®æºåãã§ããŸããïŒ
ãããã«
ããã« ããã®ãããžã§ã¯ãã®å®å
šãªã³ãŒãããããŸãã
ã¡ãã¥ãŒããŒã«ããã¢ããªã±ãŒã·ã§ã³ã§ã¡ãã¥ãŒãšãããã¢ãããèšå®ããæ¹æ³ãåŠç¿ããŸããã è€æ°ã®ã¿ã°ãŸãã¯ãã©ãŒããããããããã¹ããè©ŠããŠãåŒçšç¬ŠãããããèŠãŠã¿ãŸãããïŒ ãŸãã¯ãããã¯ãšã³ããæ¥ç¶ããŠã€ã³ã¿ãŒãããããèŠç©ãããåãåããŸããïŒ ãŸãã¯ãããŒããŒãã䜿çšããŠåŒçšç¬Šéã移åããŸããïŒ
ç 究ããã®ã«é©ããå Žæã¯ãå
¬åŒã®ããã¥ã¡ã³ã
NSMenu ã
NSPopoverããã³
NSStatusItemã§ãã