Код: Выделить всё
/// PreferenceKey to capture the bounds of the content
struct BoundsPreferenceKey: PreferenceKey {
typealias Value = Anchor?
static var defaultValue: Anchor? = nil
static func reduce(value: inout Anchor?, nextValue: () -> Anchor?) {
value = value ?? nextValue()
}
}
/// Wraps any SwiftUI `Content` in a `UIHostingController`
/// and calls you back with its `.view` so you can use it in UIKit.
struct ViewProvider: UIViewRepresentable {
let content: Content
@Binding var uiView: UIView
let bounds: CGRect
func makeUIView(context: Context) -> UIView {
let host = UIHostingController(rootView: content)
host.view.backgroundColor = .clear
host.view.bounds = bounds
DispatchQueue.main.async {
uiView = host.view
}
return host.view
}
func updateUIView(_ uiView: UIView, context: Context) {
uiView.bounds = bounds // doesn't have any effect
}
}
struct UIKitWrapperModifier: ViewModifier {
@Binding var uiView: UIView
@State var bounds = CGRect.zero
func body(content: Content) -> some View {
ViewProvider(
content: contentMeasured(content: content),
uiView: $uiView,
bounds: bounds
)
}
@ViewBuilder
func contentMeasured(content: Content) -> some View {
content
.anchorPreference(key: BoundsPreferenceKey.self, value: .bounds) { $0 }
.backgroundPreferenceValue(BoundsPreferenceKey.self) { anchor in
GeometryReader { geometry in
if let anchor {
print(geometry[anchor]) // prints correct bounds
bounds = geometry[anchor]
}
return Color.clear
}
}
}
}
extension View {
func uiKitWrapped(_ uiView: Binding) -> some View {
modifier(UIKitWrapperModifier(uiView: uiView))
}
}
< /code>
Но используя его < /p>
struct ContentView: View {
@State private var sourceUIView = UIView()
var body: some View {
Color.blue
.frame(width: 200, height: 150)
.uiKitWrapped($sourceUIView)
.background(Color.yellow)
}
}
, который изображает, что обертка Uikit не обнимает свою подветренность. Любая справка оценена. Сделайте это работать (спасибо!), Но осталась одна проблема - я опубликовал подробную информацию о иерархии моего представления, то мнение, которое я интересуется, находится внутри Scrollview и применяется соотношение сторон, что делает ширину представления действительно маленькой (10 баллов - Swiftui по умолчанию), и отладка подтверждает, что предложенный размер, вступающий в Sizethatfits nil. Упрощенная версия иерархии моего представления, которая демонстрирует проблему: < /p>
Код: Выделить всё
struct ContentView: View {
@State private var sourceUIView: UIView?
var body: some View {
ScrollView {
Rectangle()
.fill(Color.blue)
.aspectRatio(2, contentMode: .fit)
.uiKitWrapped($sourceUIView)
}
}
}
if let size {
return size
} else {
return proposal.replacingUnspecifiedDimensions(by: CGSize(width: .max, height: .max))
}
}
< /code>
С предостережением, что если соотношение сторон не установлено на представлении, оно может стать бесконечно высоким. Но не в моем случае, так что это работает.
Подробнее здесь: https://stackoverflow.com/questions/796 ... nal-layout