Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[macOS] Fix ObjC export of MultilinePillPickerView #2122

Merged
merged 8 commits into from
Jan 29, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ public final class MultilinePillPickerView: ControlHostingView {
private func updatePicker() {
let picker = MultilinePillPicker(labels: labels, action: action)
mischreiber marked this conversation as resolved.
Show resolved Hide resolved
.disabled(!isEnabled)
rootView = AnyView(picker)
hostingView.rootView = AnyView(picker)
}
}
46 changes: 34 additions & 12 deletions Sources/FluentUI_macOS/Core/ControlHostingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,54 @@
import AppKit
import SwiftUI

/// Common wrapper for hosting and exposing SwiftUI components to AppKit-based clients.
open class ControlHostingView: NSHostingView<AnyView> {
/// Common wrapper for hosting and exposing SwiftUI components to UIKit-based clients.
open class ControlHostingView: NSView {

/// The intrinsic content size of the wrapped SwiftUI view.
@objc public override var intrinsicContentSize: CGSize {
// Our desired size should always be the same as our hosted view.
return hostingView.intrinsicContentSize
}

/// Initializes and returns an instance of `ControlHostingContainer` that wraps `controlView`.
///
/// Unfortunately this class can't use Swift generics, which are incompatible with Objective-C interop. Instead we have to wrap
/// the control view in an `AnyView.`
///
/// - Parameter controlView: An `AnyView`-wrapped component to host.
/// - Parameter safeAreaRegions: Passthrough to the respective property on NSHostingView.
/// - Parameter safeAreaRegions: Passthrough to the respective property on UIHostingController.
mischreiber marked this conversation as resolved.
Show resolved Hide resolved
/// Indicates which safe area regions the underlying hosting controller should add to its view.
public init(_ controlView: AnyView, safeAreaRegions: SafeAreaRegions = .all) {
super.init(rootView: controlView)
hostingView = NSHostingView.init(rootView: controlView)
if #available(macOS 13.3, *) {
self.sizingOptions = [.intrinsicContentSize]
self.safeAreaRegions = safeAreaRegions
hostingView.sizingOptions = [.intrinsicContentSize]
hostingView.safeAreaRegions = safeAreaRegions
}

layer?.backgroundColor = .clear
translatesAutoresizingMaskIntoConstraints = false
super.init(frame: .zero)

self.configureHostedView()
}

@MainActor @preconcurrency required public init?(coder: NSCoder) {
required public init?(coder: NSCoder) {
preconditionFailure("init(coder:) has not been implemented")
}

@MainActor @preconcurrency required public init(rootView: AnyView) {
preconditionFailure("init(rootView:) has not been implemented")

let hostingView: NSHostingView<AnyView>

/// Adds `hostingController.view` to ourselves as a subview, and enables necessary constraints.
private func configureHostedView() {
hostingView.layer?.backgroundColor = NSColor.clear.cgColor

addSubview(hostingView)
hostingView.translatesAutoresizingMaskIntoConstraints = false

let requiredConstraints = [
hostingView.leadingAnchor.constraint(equalTo: leadingAnchor),
hostingView.trailingAnchor.constraint(equalTo: trailingAnchor),
hostingView.bottomAnchor.constraint(equalTo: bottomAnchor),
hostingView.topAnchor.constraint(equalTo: topAnchor)
]
self.addConstraints(requiredConstraints)
}
}
Loading