Swift 6 language mode and a consistent macOS 14 baseline - #64
Open
matijazezelj wants to merge 4 commits into
Open
matijazezelj wants to merge 4 commits into
matijazezelj wants to merge 4 commits into
Conversation
Bundle(url:) returns nil once an app is moved, renamed or uninstalled, so force-unwrapping it in RuleItem.body trapped the moment the Rules tab laid out its List — making a stale rule impossible to reach and delete. Rows for unresolved apps now render in a degraded state instead of being force-unwrapped or hidden, so they can still be edited or removed. Apply the same treatment to CFBundleName and bundleIdentifier, which are both optional in practice, and to the equivalent sites in the Apps tab, Browsers tab and the picker. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DWQa3xpkwVRtrtVh8VkQQo
The symbol survives in SwiftUI.tbd but is absent from the swiftinterface of both the macOS 26.5 and 27.0 SDKs, so the call no longer compiles against any current SDK. scrollEdgeEffectHidden(_:for:) carries the same @available(macOS 26.0, *) and slots straight into the existing guard. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DWQa3xpkwVRtrtVh8VkQQo
Unify MACOSX_DEPLOYMENT_TARGET on 14.0 — it read 14.4 at project level but 13.0 at target level, so the effective minimum was silently 13.0 — and move the target to Swift 6 language mode. With 13.0 gone the two availability shims are dead weight: call onKeyPress and focusEffectDisabled directly and delete View+OnKeyPress.swift and View+FocusEffectDisabled.swift. Adopt the two-parameter onChange. Replace two overrides declared in extensions of ObjC classes, which is undefined behaviour in Swift and picks a winner arbitrarily when more than one exists. canBecomeKey belongs on BrowserinoWindow, the only panel that needs it, rather than on every NSPanel including the open and save panels. The NSTableView background hack becomes scrollContentBackground(.hidden) on the four Lists it was there to serve. AppDelegate is @mainactor; observeValue stays nonisolated because defaults written by another process arrive off the main thread. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DWQa3xpkwVRtrtVh8VkQQo
Errors and warnings that only surface in a full compile, not in -typecheck. BrowserUtil's static @AppStorage properties are nonisolated global mutable state; the type is only ever touched from the main actor, so isolate it there. SettingsDocument holds [String: Any] while FileDocument requires Sendable. Serialize on the way in and carry Data instead — the exporter wrote the same pretty-printed JSON either way. setDefaultApplication's completion handler is a Sendable closure and cannot touch @State or call a main-actor method, so hop before updating isDefault. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DWQa3xpkwVRtrtVh8VkQQo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The one thing to decide first
This raises the minimum macOS from 13 to 14. That is a product call, not a technical one, so it's entirely yours — everything else here follows from it, and I've kept it in separate commits so you can take the parts you want.
Worth knowing: the current setting is already inconsistent.
MACOSX_DEPLOYMENT_TARGETis14.4in both project-level configs but13.0in both target-level ones, and target-level wins — so the effective minimum today is 13.0, while the project level advertises 14.4. Whichever way you go, those four values should agree.What raising it buys
Two availability shims become dead code and are deleted outright — 90 lines, including a whole
NSViewRepresentablekeyboard fallback:View+OnKeyPress.swift→ callonKeyPressdirectlyView+FocusEffectDisabled.swift→ callfocusEffectDisableddirectlyThe deprecated single-parameter
onChange(of:perform:)atShortcutButton.swift:25andGeneralTab.swift:203moves to the two-parameter form, which needs macOS 14.Two overrides declared in extensions
These are worth a look regardless of the baseline question. Overriding a method from an extension of an Objective-C class is undefined behaviour in Swift — if more than one such override exists, which one wins is not defined.
BrowserinoWindow.swift:51forcedcanBecomeKeytotrueon everyNSPanelin the process, which includes the open and save panels behindfileImporter. Moved ontoBrowserinoWindow, the only panel that actually needs it (its.nonactivatingPanelstyle is what refuses key status).PreferencesView.swift:12overrodeNSTableView.viewDidMoveToWindowapp-wide to clear List backgrounds. Replaced with.scrollContentBackground(.hidden)on the four Lists it existed to serve — the sanctioned API, available since macOS 13.Swift 6 language mode
SWIFT_VERSION5.0 → 6.0.AppDelegatebecomes@MainActor, which resolves 15 of 16 isolation warnings. The sixteenth isobserveValue, deliberately leftnonisolatedwith a hop to the main actor inside: defaults written by another process deliver KVO off the main thread, soMainActor.assumeIsolatedwould trap there. That isn't hypothetical — it fires if you edit Browserino's rules withdefaults writewhile the app is running.Three further fixes that only appear in a full compile, never in
-typecheck:BrowserUtil's static@AppStorageproperties are nonisolated global mutable state (a hard error in Swift 6). The type is only ever used from the main actor, so it's isolated there.SettingsDocumentheld[String: Any]whileFileDocumentrequiresSendable. It now serializes on the way in and carriesData; the exporter wrote the same pretty-printed JSON either way.setDefaultApplication's completion handler is a@Sendableclosure and cannot touch@Stateor call a main-actor method, so it hops before updatingisDefault.Verification
Compiles with 0 errors and 0 warnings in Swift 6 mode against the macOS 26.5 SDK, targeting macOS 14.0, and the resulting app has been running as my default browser on macOS 27.
Not verified, and worth your eyes: the List backgrounds under
scrollContentBackground(.hidden), shortcut recording via the directonKeyPress, and the menu-bar toggle, which is now one main-actor hop later than before. I had no way to screenshot the running UI on this machine.LastUpgradeCheckis deliberately untouched — Xcode rewrites it itself when you accept its recommended-settings prompt, and setting it by hand without Xcode validating those settings would be a lie in the file.Disclosure
Written with AI assistance (Claude Code), same as #63. Everything above was compiled and run before submitting. This one is much more opinionated than #63, so treat it as a proposal rather than a fix — no hard feelings if the baseline bump isn't where you want to go.