Skip to content

Update AppKit Components & Examples#784

Merged
Kyle-Ye merged 2 commits intomainfrom
bugfix/ns_hosting_controller
Feb 8, 2026
Merged

Update AppKit Components & Examples#784
Kyle-Ye merged 2 commits intomainfrom
bugfix/ns_hosting_controller

Conversation

@Mx-Iris
Copy link
Collaborator

@Mx-Iris Mx-Iris commented Feb 8, 2026

No description provided.

Copilot AI review requested due to automatic review settings February 8, 2026 13:21
@Mx-Iris Mx-Iris requested a review from Kyle-Ye as a code owner February 8, 2026 13:21
@github-actions github-actions bot added enhancement New feature or request platform: macOS labels Feb 8, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the AppKit hosting integration to better participate in Auto Layout sizing, window lifecycle coordination, and example app setup.

Changes:

  • Added sizing/intrinsic-content-size logic and window/content-size constraint management to NSHostingView.
  • Extended NSHostingController to expose sceneBridgingOptions, participate in sizing via preferredContentSize, and set its view during common init.
  • Updated AppKit app delegate + hosting example to construct windows via NSWindow(contentViewController:) and keep strong references to window controllers.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
Sources/OpenSwiftUI/Integration/Hosting/AppKit/View/NSHostingView.swift Adds constraint/sizing behaviors, window notifications, and environment/container updates.
Sources/OpenSwiftUI/Integration/Hosting/AppKit/Controller/NSHostingController.swift Wires hosting view as controller’s view and exposes additional sizing/scene-bridging APIs.
Sources/OpenSwiftUI/App/App/AppKit/AppKitAppDelegate.swift Updates window creation to use contentViewController and retains the window controller.
Example/HostingExample/ViewController.swift Switches macOS example to a window-controller-based setup using NSHostingController.
Example/HostingExample/AppDelegate.swift Removes now-duplicated window controller and relies on the new macOS setup.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +354 to +361
center.addObserver(self, selector: #selector(windowDidChangeMain), name: NSWindow.didBecomeMainNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidChangeMain), name: NSWindow.didResignMainNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidChangeKey), name: NSWindow.didBecomeKeyNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidChangeKey), name: NSWindow.didResignKeyNotification, object: newWindow)
// TODO: NSWindowDidOrderOnScreenNotification / NSWindowDidOrderOffScreenNotification → windowDidChangeVisibility
center.addObserver(self, selector: #selector(windowWillBeginSheet), name: NSWindow.willBeginSheetNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidEndSheet), name: NSWindow.didEndSheetNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidChangeScreen), name: NSWindow.didChangeScreenNotification, object: newWindow)
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The observers added in viewWillMove(toWindow:) use #selector(windowDidChangeMain)/etc, but the corresponding handler methods should be #selector(windowDidChangeMain(_:)) (and so on) to match NotificationCenter’s required method signature. Update both the selector and method signatures consistently.

Suggested change
center.addObserver(self, selector: #selector(windowDidChangeMain), name: NSWindow.didBecomeMainNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidChangeMain), name: NSWindow.didResignMainNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidChangeKey), name: NSWindow.didBecomeKeyNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidChangeKey), name: NSWindow.didResignKeyNotification, object: newWindow)
// TODO: NSWindowDidOrderOnScreenNotification / NSWindowDidOrderOffScreenNotification → windowDidChangeVisibility
center.addObserver(self, selector: #selector(windowWillBeginSheet), name: NSWindow.willBeginSheetNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidEndSheet), name: NSWindow.didEndSheetNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidChangeScreen), name: NSWindow.didChangeScreenNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidChangeMain(_:)), name: NSWindow.didBecomeMainNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidChangeMain(_:)), name: NSWindow.didResignMainNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidChangeKey(_:)), name: NSWindow.didBecomeKeyNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidChangeKey(_:)), name: NSWindow.didResignKeyNotification, object: newWindow)
// TODO: NSWindowDidOrderOnScreenNotification / NSWindowDidOrderOffScreenNotification → windowDidChangeVisibility
center.addObserver(self, selector: #selector(windowWillBeginSheet(_:)), name: NSWindow.willBeginSheetNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidEndSheet(_:)), name: NSWindow.didEndSheetNotification, object: newWindow)
center.addObserver(self, selector: #selector(windowDidChangeScreen(_:)), name: NSWindow.didChangeScreenNotification, object: newWindow)

Copilot uses AI. Check for mistakes.
@augmentcode
Copy link

augmentcode bot commented Feb 8, 2026

🤖 Augment PR Summary

Summary: This PR updates the AppKit hosting components and the macOS hosting example to better align window/controller setup and begin fleshing out sizing/window-bridging behavior.

Changes:

  • Refactors the macOS example to use an NSWindowController that directly creates an NSWindow with an NSHostingController as its contentViewController.
  • Updates AppKitAppDelegate to create the window via NSWindow(contentViewController:) and retain the window controller instance.
  • Moves NSHostingController view setup into a shared initializer path and adds API surface for sceneBridgingOptions, preferredContentSize derivation, and identifier propagation.
  • Significantly extends NSHostingView with intrinsic-size caching, constraint update handling, window notification wiring, container/environment update hooks, and window content min/max size synchronization.

Technical Notes: The new AppKit hosting behavior introduces more Auto Layout integration and window-awareness (constraints + content size extrema), and begins scaffolding “scene/window bridging” options for future toolbar/title integration.

🤖 Was this summary useful? React with 👍 or 👎

Copy link

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 4 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

guard sizingOptions.contains(.intrinsicContentSize),
!checkForReentrantLayout()
else {
return cachedIntrinsicContentSize
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intrinsicContentSize returns cachedIntrinsicContentSize when .intrinsicContentSize isn’t in sizingOptions; if sizingOptions is toggled from enabled → disabled, the cached value could keep advertising an intrinsic size unexpectedly. Consider ensuring the “disabled” path reports no intrinsic metric (or clears the cache) so sizingOptions = [] truly opts out.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

}

if let newWindow {
center.addObserver(self, selector: #selector(windowDidChangeMain), name: NSWindow.didBecomeMainNotification, object: newWindow)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The view registers for multiple NSWindow notifications via NotificationCenter in viewWillMove(toWindow:); if the view is deallocated without a final move to nil, those observers can still fire and message a freed object. Consider also removing observers in deinit as a safety net.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

}

// TODO: screen.displayID
let displayID = CGMainDisplayID()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

startAsyncRendering() always creates the display link using CGMainDisplayID() without checking window?.screen, which can schedule rendering even when the view isn’t in a window (and can target the wrong display’s refresh characteristics). It seems safer to gate display-link creation on having an attached window/screen (or otherwise deliberately document why main display is correct).

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

/// window, the default value for this property will be `.all`, which
/// includes the options for `.toolbars` and `.title`. Otherwise, the
/// default value is `[]`.
public var sceneBridgingOptions: NSHostingSceneBridgingOptions {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs for sceneBridgingOptions say the default becomes .all when used as a window’s contentViewController, but the current implementation only forwards to host.sceneBridgingOptions (which defaults to []). This looks like a docs/behavior mismatch that could confuse callers relying on the documented default.

Severity: low

Other Locations
  • Sources/OpenSwiftUI/Integration/Hosting/AppKit/View/NSHostingView.swift:102

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

@codecov
Copy link

codecov bot commented Feb 8, 2026

Codecov Report

❌ Patch coverage is 54.92063% with 142 lines in your changes missing coverage. Please review.
✅ Project coverage is 26.57%. Comparing base (1ff649d) to head (c3e21c9).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...ntegration/Hosting/AppKit/View/NSHostingView.swift 56.37% 130 Missing ⚠️
...osting/AppKit/Controller/NSHostingController.swift 35.71% 9 Missing ⚠️
...OpenSwiftUI/App/App/AppKit/AppKitAppDelegate.swift 0.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #784      +/-   ##
==========================================
+ Coverage   26.19%   26.57%   +0.37%     
==========================================
  Files         650      650              
  Lines       40232    40529     +297     
==========================================
+ Hits        10539    10769     +230     
- Misses      29693    29760      +67     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Kyle-Ye Kyle-Ye force-pushed the bugfix/ns_hosting_controller branch from fd8e792 to c3e21c9 Compare February 8, 2026 14:15
@github-actions github-actions bot added the documentation Improvements or additions to documentation label Feb 8, 2026
@Kyle-Ye Kyle-Ye merged commit 9916291 into main Feb 8, 2026
7 of 8 checks passed
@Kyle-Ye Kyle-Ye deleted the bugfix/ns_hosting_controller branch February 8, 2026 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request platform: macOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants