Skip to content

Commit 7582a12

Browse files
committed
Clean up selector warnings (AppKit) and typos (AppBackend)
1 parent be8e209 commit 7582a12

File tree

2 files changed

+41
-17
lines changed

2 files changed

+41
-17
lines changed

Sources/AppKitBackend/AppKitBackend.swift

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -233,53 +233,77 @@ public final class AppKitBackend: AppBackend {
233233
return appMenu
234234
}
235235

236+
/// A vessel for empty methods that we use to construct selectors. We only
237+
/// do it this way, because Swift complains if we provide method selectors
238+
/// such as `undo:` and `redo:` as strings (even though they don't come
239+
/// from any particular class as far as I can tell).
240+
///
241+
/// I've failed to find which class (if any) these methods are supposed to
242+
/// come from, and the following Apple documentation article makes it sound
243+
/// like undo and redo are just stringly-typed objc messages:
244+
/// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/UndoArchitecture/Articles/AppKitUndo.html
245+
class FirstResponder {
246+
/// I'm not sure exactly what type this first argument is meant to have,
247+
/// but I believe that it actually doesn't matter, because the number
248+
/// of parameters (and their corresponding labels) are what actually matter.
249+
@objc func undo(_ sender: NSObject) {}
250+
@objc func redo(_ sender: NSObject) {}
251+
}
252+
236253
public static func createDefaultEditMenu() -> NSMenu {
237-
let appMenu = NSMenu(title: "Edit")
238-
let undoItem = appMenu.addItem(
254+
// You may notice that multiple different base types are used in the
255+
// action selectors of the various menu items. This is because the
256+
// selectors get sent to the app's first responder at the time of
257+
// the command getting sent. If the first responder doesn't have a
258+
// method matching the selector, then AppKit automatically disables
259+
// the corresponding menu item.
260+
261+
let editMenu = NSMenu(title: "Edit")
262+
let undoItem = editMenu.addItem(
239263
withTitle: "Undo",
240-
action: "undo:",
264+
action: #selector(FirstResponder.undo(_:)),
241265
keyEquivalent: "z"
242266
)
243267
undoItem.keyEquivalentModifierMask = .command
244268

245-
let redoItem = appMenu.addItem(
269+
let redoItem = editMenu.addItem(
246270
withTitle: "Redo",
247-
action: "redo:",
271+
action: #selector(FirstResponder.redo(_:)),
248272
keyEquivalent: "z"
249273
)
250274
redoItem.keyEquivalentModifierMask = [.command, .shift]
251275

252-
appMenu.addItem(NSMenuItem.separator())
276+
editMenu.addItem(NSMenuItem.separator())
253277

254-
let cutItem = appMenu.addItem(
278+
let cutItem = editMenu.addItem(
255279
withTitle: "Cut",
256-
action: "cut:",
280+
action: #selector(NSTextView.cut),
257281
keyEquivalent: "x"
258282
)
259283
cutItem.keyEquivalentModifierMask = .command
260284

261-
let copyItem = appMenu.addItem(
285+
let copyItem = editMenu.addItem(
262286
withTitle: "Copy",
263-
action: "copy:",
287+
action: #selector(NSTextView.copy),
264288
keyEquivalent: "c"
265289
)
266290
copyItem.keyEquivalentModifierMask = .command
267291

268-
let pasteItem = appMenu.addItem(
292+
let pasteItem = editMenu.addItem(
269293
withTitle: "Paste",
270-
action: "paste:",
294+
action: #selector(NSTextView.paste),
271295
keyEquivalent: "v"
272296
)
273297
pasteItem.keyEquivalentModifierMask = .command
274298

275-
let selectAllItem = appMenu.addItem(
299+
let selectAllItem = editMenu.addItem(
276300
withTitle: "Select all",
277-
action: "selectAll:",
301+
action: #selector(NSTextView.selectAll),
278302
keyEquivalent: "a"
279303
)
280304
selectAllItem.keyEquivalentModifierMask = .command
281305

282-
return appMenu
306+
return editMenu
283307
}
284308

285309
public func setApplicationMenu(_ submenus: [ResolvedMenu.Submenu]) {

Sources/SwiftCrossUI/Backend/AppBackend.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,11 +474,11 @@ public protocol AppBackend {
474474
/// Gets the value of an editable text field.
475475
func getContent(ofTextField textField: Widget) -> String
476476

477-
/// Creates a editable multi-line text editor with a placeholder label and change
477+
/// Creates an editable multi-line text editor with a placeholder label and change
478478
/// handler. The change handler is called whenever the displayed value changes.
479479
/// Predominantly used by ``TextEditor``.
480480
func createTextEditor() -> Widget
481-
/// Sets the placeholder label and change handler of a editable multi-line text editor.
481+
/// Sets the placeholder label and change handler of an editable multi-line text editor.
482482
/// The new change handler replaces any existing change handlers, and is called
483483
/// whenever the displayed value changes.
484484
///

0 commit comments

Comments
 (0)