Skip to content

Commit aa8f2c0

Browse files
authored
Add geometry change invalidation support (#881)
1 parent bc26339 commit aa8f2c0

5 files changed

Lines changed: 64 additions & 4 deletions

File tree

Sources/COpenSwiftUI/Shims/UIKit/UIKit_Private.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ OPENSWIFTUI_ASSUME_NONNULL_BEGIN
3636

3737
@interface UIView (OpenSwiftUI_SPI)
3838
- (instancetype)_initWithLayer:(CALayer *)layer;
39+
- (void)_geometryChanged:(const void *)geometry forAncestor:(nullable UIView *)ancestor;
40+
- (void)_registerForGeometryChanges;
41+
- (void)_unregisterForGeometryChanges;
3942
- (BOOL)_shouldAnimatePropertyWithKey_openswiftui_safe_wrapper:(NSString *)key OPENSWIFTUI_SWIFT_NAME(_shouldAnimateProperty(withKey:));
4043
- (void)_setFocusInteractionEnabled_openswiftui_safe_wrapper:(BOOL)enabled OPENSWIFTUI_SWIFT_NAME(_setFocusInteractionEnabled(_:));
4144
@property(nonatomic, readonly, nullable) UIViewController *_viewControllerForAncestor_openswiftui_safe_wrapper OPENSWIFTUI_SWIFT_NAME(_viewControllerForAncestor);

Sources/OpenSwiftUI/Integration/Hosting/UIKit/View/UIHostingView+Extension.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,18 @@ extension _UIHostingView: ViewRendererHost {
280280
}
281281

282282
package func updateTransform() {
283+
base.updateTransform()
284+
285+
// TODO: Notify UIKit related bridges
283286
_openSwiftUIUnimplementedWarning()
287+
288+
if !safeAreaRegions.contains(.container) {
289+
invalidateProperties(.safeArea, mayDeferUpdate: false)
290+
}
291+
}
292+
293+
package func updateTransformWithoutGeometryObservation() {
294+
base.updateTransformWithoutGeometryObservation()
284295
}
285296

286297
package func updateSize() {
@@ -356,6 +367,11 @@ extension _UIHostingView {
356367

357368
extension _UIHostingView: RootTransformProvider {
358369
package func rootTransform() -> ViewTransform {
370+
if !_base.registeredForGeometryChanges {
371+
_base.registeredForGeometryChanges = true
372+
_registerForGeometryChanges()
373+
}
374+
// TODO
359375
_openSwiftUIUnimplementedWarning()
360376
return .init()
361377
}
@@ -392,4 +408,3 @@ public func _makeUIHostingView<Content>(_ view: Content) -> NSObject where Conte
392408
}
393409

394410
#endif
395-

Sources/OpenSwiftUI/Integration/Hosting/UIKit/View/UIHostingView.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,13 @@ open class _UIHostingView<Content>: UIView, XcodeViewDebugDataProvider where Con
243243
base.layoutSubviews()
244244
}
245245

246+
override dynamic open func _geometryChanged(
247+
_ geometry: UnsafeRawPointer,
248+
forAncestor ancestor: UIView?
249+
) {
250+
base._geometryChanged(geometry, forAncestor: ancestor)
251+
}
252+
246253
override dynamic open var frame: CGRect {
247254
get {
248255
super.frame

Sources/OpenSwiftUI/Integration/Hosting/UIKit/View/UIHostingViewBase.swift

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,30 @@ package class UIHostingViewBase {
230230
}
231231
}
232232

233+
@inline(__always)
234+
func updateTransform() {
235+
guard let uiView else {
236+
return
237+
}
238+
if !viewGraph.invalidateTransform(), registeredForGeometryChanges {
239+
uiView._unregisterForGeometryChanges()
240+
registeredForGeometryChanges = false
241+
}
242+
}
243+
233244
package func updateTransformWithoutGeometryObservation() {
234-
_openSwiftUIUnimplementedFailure()
245+
guard let uiView else {
246+
return
247+
}
248+
let wasRegisteredForGeometryChanges = registeredForGeometryChanges
249+
if !viewGraph.invalidateTransform(), registeredForGeometryChanges {
250+
uiView._unregisterForGeometryChanges()
251+
registeredForGeometryChanges = false
252+
}
253+
if !wasRegisteredForGeometryChanges, registeredForGeometryChanges {
254+
uiView._unregisterForGeometryChanges()
255+
registeredForGeometryChanges = false
256+
}
235257
}
236258

237259
@inline(__always)
@@ -510,7 +532,14 @@ package class UIHostingViewBase {
510532
}
511533

512534
package func _geometryChanged(_: UnsafeRawPointer, forAncestor: UIView?) {
513-
_openSwiftUIUnimplementedFailure()
535+
guard let host else {
536+
return
537+
}
538+
if registeredForGeometryChanges {
539+
host.invalidateProperties(.transform, mayDeferUpdate: false)
540+
} else if !options.contains(.registeredForGeometryChanges) {
541+
Log.internalError("Received _geometryChanged with no registration for \(self).")
542+
}
514543
}
515544

516545
package func layoutSubviews() {

Sources/OpenSwiftUICore/View/Graph/ViewGraph.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,13 @@ extension ViewGraph {
377377

378378
@discardableResult
379379
package func invalidateTransform() -> Bool {
380-
_openSwiftUIUnimplementedFailure()
380+
let rootTransform = $rootTransform
381+
guard !rootTransform.valueState.contains(.dirty) else {
382+
return false
383+
}
384+
rootTransform.invalidateValue()
385+
delegate?.graphDidChange()
386+
return true
381387
}
382388
}
383389

0 commit comments

Comments
 (0)