Skip to content

Commit 9916291

Browse files
Mx-IrisKyle-Ye
andauthored
Update AppKit Components & Examples (#784)
* Update AppKit Components & Examples * Update documentation --------- Co-authored-by: Kyle <kyle201817146@gmail.com>
1 parent 1ff649d commit 9916291

File tree

5 files changed

+539
-90
lines changed

5 files changed

+539
-90
lines changed

Example/HostingExample/AppDelegate.swift

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -63,30 +63,4 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
6363
}
6464
}
6565

66-
final class WindowController: NSWindowController {
67-
init() {
68-
super.init(window: nil)
69-
}
70-
71-
@available(*, unavailable)
72-
required init?(coder: NSCoder) {
73-
fatalError("init(coder:) has not been implemented")
74-
}
75-
76-
override var windowNibName: NSNib.Name? { "" }
77-
78-
lazy var viewController = ViewController()
79-
80-
override func loadWindow() {
81-
window = NSWindow(contentRect: .init(x: 0, y: 0, width: 500, height: 300), styleMask: [.titled, .closable, .miniaturizable], backing: .buffered, defer: false)
82-
window?.center()
83-
}
84-
85-
override func windowDidLoad() {
86-
super.windowDidLoad()
87-
88-
contentViewController = viewController
89-
}
90-
}
91-
9266
#endif

Example/HostingExample/ViewController.swift

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ import UIKit
1717
import AppKit
1818
#endif
1919

20-
import OpenSwiftUI
21-
2220
#if os(iOS) || os(visionOS)
2321
class ViewController: UINavigationController {
2422
override func viewDidAppear(_ animated: Bool) {
@@ -51,21 +49,21 @@ final class EntryViewController: UIViewController {
5149
}
5250
}
5351
#elseif os(macOS)
54-
class ViewController: NSViewController {
55-
override func loadView() {
56-
view = NSHostingView(rootView: ContentView())
52+
final class WindowController: NSWindowController {
53+
init() {
54+
super.init(window: nil)
5755
}
5856

59-
override func viewDidLoad() {
60-
super.viewDidLoad()
61-
62-
view.frame = .init(x: 0, y: 0, width: 500, height: 300)
57+
@available(*, unavailable)
58+
required init?(coder: NSCoder) {
59+
fatalError("init(coder:) has not been implemented")
6360
}
6461

65-
override var representedObject: Any? {
66-
didSet {
67-
// Update the view, if already loaded.
68-
}
62+
override var windowNibName: NSNib.Name? { "" }
63+
64+
override func loadWindow() {
65+
window = NSWindow(contentViewController: NSHostingController(rootView: ContentView().frame(width: 500, height: 300)))
66+
window?.center()
6967
}
7068
}
7169
#endif

Sources/OpenSwiftUI/App/App/AppKit/AppKitAppDelegate.swift

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,13 @@ class AppDelegate: NSResponder, NSApplicationDelegate {
5959
// FIXME
6060
let items = AppGraph.shared?.rootSceneList?.items ?? []
6161
let view = items[0].value.view
62-
let hostingVC = NSHostingController(rootView: view)
62+
let hostingVC = NSHostingController(rootView: view.frame(width: 500, height: 300))
6363
let windowVC = WindowController(hostingVC)
6464
windowVC.showWindow(nil)
65+
self.windowVC = windowVC
6566
}
67+
68+
var windowVC: NSWindowController?
6669
}
6770

6871
// FIXME: frame is zero
@@ -82,15 +85,9 @@ final class WindowController<Content>: NSWindowController where Content: View {
8285
let hostingVC: NSHostingController<Content>
8386

8487
override func loadWindow() {
85-
window = NSWindow(contentRect: .init(x: 0, y: 0, width: 500, height: 300), styleMask: [.titled, .closable, .miniaturizable], backing: .buffered, defer: false)
88+
window = NSWindow(contentViewController: hostingVC)
8689
window?.center()
8790
}
88-
89-
override func windowDidLoad() {
90-
super.windowDidLoad()
91-
contentViewController = hostingVC
92-
hostingVC.host.frame = window!.frame
93-
}
9491
}
9592

9693
// MARK: - App Utils

Sources/OpenSwiftUI/Integration/Hosting/AppKit/Controller/NSHostingController.swift

Lines changed: 69 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99

1010
public import AppKit
1111

12-
/// An AppKit view controller that hosts SwiftUI view hierarchy.
12+
/// An AppKit view controller that hosts OpenSwiftUI view hierarchy.
1313
///
14-
/// Create an `NSHostingController` object when you want to integrate SwiftUI
15-
/// views into an AppKit view hierarchy. At creation time, specify the SwiftUI
14+
/// Create an `NSHostingController` object when you want to integrate OpenSwiftUI
15+
/// views into an AppKit view hierarchy. At creation time, specify the OpenSwiftUI
1616
/// view you want to use as the root view for this view controller; you can
1717
/// change that view later using the ``NSHostingController/rootView`` property.
1818
/// Use the hosting controller like you would any other view controller, by
@@ -26,10 +26,10 @@ public import AppKit
2626
open class NSHostingController<Content>: NSViewController where Content: View {
2727
var host: NSHostingView<Content>
2828

29-
/// Creates a hosting controller object that wraps the specified SwiftUI
29+
/// Creates a hosting controller object that wraps the specified OpenSwiftUI
3030
/// view.
3131
///
32-
/// - Parameter rootView: The root view of the SwiftUI view hierarchy that
32+
/// - Parameter rootView: The root view of the OpenSwiftUI view hierarchy that
3333
/// you want to manage using the hosting view controller.
3434
public init(rootView: Content) {
3535
// TODO
@@ -39,11 +39,11 @@ open class NSHostingController<Content>: NSViewController where Content: View {
3939
}
4040

4141
/// Creates a hosting controller object from an archive and the specified
42-
/// SwiftUI view.
42+
/// OpenSwiftUI view.
4343
///
4444
/// - Parameters:
4545
/// - coder: The decoder to use during initialization.
46-
/// - rootView: The root view of the SwiftUI view hierarchy that you want
46+
/// - rootView: The root view of the OpenSwiftUI view hierarchy that you want
4747
/// to manage using this view controller.
4848
public init?(coder: NSCoder, rootView: Content) {
4949
// TODO
@@ -54,6 +54,7 @@ open class NSHostingController<Content>: NSViewController where Content: View {
5454

5555
func _commonInit() {
5656
host.viewController = self
57+
self.view = host
5758
}
5859

5960
/// Creates a hosting controller object from the contents of the specified
@@ -68,11 +69,9 @@ open class NSHostingController<Content>: NSViewController where Content: View {
6869
public required init?(coder: NSCoder) {
6970
preconditionFailure("init(coder:) must be implemented in a subclass and call super.init(coder:, rootView:)")
7071
}
71-
72-
open override func loadView() {
73-
view = host
74-
}
75-
72+
73+
/// The root view of the OpenSwiftUI view hierarchy managed by this view
74+
/// controller.
7675
public var rootView: Content {
7776
get { host.rootView }
7877
set { host.rootView = newValue }
@@ -88,23 +87,23 @@ open class NSHostingController<Content>: NSViewController where Content: View {
8887
}
8988

9089
/// The options for how the hosting controller's view creates and updates
91-
/// constraints based on the size of its SwiftUI content.
90+
/// constraints based on the size of its OpenSwiftUI content.
9291
///
9392
/// NSHostingController can create minimum, maximum, and ideal (content
94-
/// size) constraints that are derived from its SwiftUI view content. These
93+
/// size) constraints that are derived from its OpenSwiftUI view content. These
9594
/// constraints are only created when Auto Layout constraints are otherwise
9695
/// being used in the containing window.
9796
///
9897
/// If the NSHostingController is set as the `contentViewController` of an
9998
/// `NSWindow`, it will also update the window's `contentMinSize` and
100-
/// `contentMaxSize` based on the minimum and maximum size of its SwiftUI
99+
/// `contentMaxSize` based on the minimum and maximum size of its OpenSwiftUI
101100
/// content.
102101
///
103102
/// `sizingOptions` defaults to `.standardBounds` (which includes
104103
/// `minSize`, `intrinsicContentSize`, and `maxSize`), but can be set to an
105104
/// explicit value to control this behavior. For instance, setting a value
106105
/// of `.minSize` will only create the constraints necessary to maintain the
107-
/// minimum size of the SwiftUI content, or setting a value of `[]` will
106+
/// minimum size of the OpenSwiftUI content, or setting a value of `[]` will
108107
/// create no constraints at all.
109108
///
110109
/// If a use case can make assumptions about the size of the
@@ -113,7 +112,7 @@ open class NSHostingController<Content>: NSViewController where Content: View {
113112
/// fewer options can improve performance as it reduces the amount of layout
114113
/// measurements that need to be performed. If an `NSHostingController` has
115114
/// a `frame` that is smaller or larger than that required to display its
116-
/// SwiftUI content, the content will be centered within that frame.
115+
/// OpenSwiftUI content, the content will be centered within that frame.
117116
public var sizingOptions: NSHostingSizingOptions {
118117
get { host.sizingOptions }
119118
set { host.sizingOptions = newValue }
@@ -127,6 +126,55 @@ open class NSHostingController<Content>: NSViewController where Content: View {
127126
set { host.safeAreaRegions = newValue }
128127
}
129128

129+
/// The options for which aspects of the window will be managed by this
130+
/// controller's hosting view.
131+
///
132+
/// `NSHostingController` will populate certain aspects of its associated
133+
/// window, depending on which options are specified.
134+
///
135+
/// For example, a hosting controller can manage its window's toolbar by
136+
/// including the `.toolbars` option:
137+
///
138+
/// struct RootView: View {
139+
/// var body: some View {
140+
/// ContentView()
141+
/// .toolbar {
142+
/// MyToolbarContent()
143+
/// }
144+
/// }
145+
/// }
146+
///
147+
/// let controller = NSHostingController(rootView: RootView())
148+
/// controller.sceneBridgingOptions = [.toolbars]
149+
///
150+
/// When this hosting controller is set as the `contentViewController` for a
151+
/// window, the default value for this property will be `.all`, which
152+
/// includes the options for `.toolbars` and `.title`. Otherwise, the
153+
/// default value is `[]`.
154+
public var sceneBridgingOptions: NSHostingSceneBridgingOptions {
155+
get { host.sceneBridgingOptions }
156+
set { host.sceneBridgingOptions = newValue }
157+
}
158+
159+
open override var preferredContentSize: NSSize {
160+
get {
161+
if sizingOptions.contains(.preferredContentSize) {
162+
return host.idealSize()
163+
} else {
164+
return super.preferredContentSize
165+
}
166+
}
167+
set {
168+
super.preferredContentSize = newValue
169+
}
170+
}
171+
172+
open override var identifier: NSUserInterfaceItemIdentifier? {
173+
didSet {
174+
host.identifier = identifier
175+
}
176+
}
177+
130178
/// Calculates and returns the most appropriate size for the current view.
131179
///
132180
/// - Parameter size: The proposed new size for the view.
@@ -140,6 +188,10 @@ open class NSHostingController<Content>: NSViewController where Content: View {
140188
return result
141189
}
142190

191+
public func _render(seconds: Double) {
192+
host.render(interval: seconds, targetTimestamp: nil)
193+
}
194+
143195
public func _forEachIdentifiedView(body: (_IdentifiedViewProxy) -> Void) {
144196
host.forEachIdentifiedView(body: body)
145197
}

0 commit comments

Comments
 (0)