Skip to content

Commit da3e595

Browse files
committed
Add UIKitUpdateCycle API
1 parent c3a3efb commit da3e595

File tree

3 files changed

+107
-3
lines changed

3 files changed

+107
-3
lines changed

Sources/COpenSwiftUI/Shims/UIKit/UIKit_Private.h

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,52 @@ bool UIViewIgnoresTouchEvents(UIView *view);
9191
OPENSWIFTUI_EXPORT
9292
float UIAnimationDragCoefficient(void);
9393

94+
UIView * _UIKitCreateCustomView(Class class, CALayer *layer);
95+
9496
// MARK: - UIUpdate related private API from UIKitCore
9597

9698
OPENSWIFTUI_EXPORT
97-
bool _UIUpdateAdaptiveRateNeeded();
99+
bool _UIUpdateAdaptiveRateNeeded(void);
98100

99-
UIView * _UIKitCreateCustomView(Class class, CALayer *layer);
101+
OPENSWIFTUI_EXPORT
102+
bool _UIUpdateCycleEnabled(void);
103+
104+
typedef struct _UIUpdateTiming {
105+
uint64_t unknown1;
106+
uint64_t unknown2;
107+
uint64_t unknown3;
108+
} _UIUpdateTiming;
109+
110+
typedef void (^_UIUpdateSequenceCallback)(void * _Nullable context, CGFloat time, const _UIUpdateTiming * _Nonnull timing);
111+
112+
typedef struct _UIUpdateSequenceItem _UIUpdateSequenceItem;
113+
114+
typedef struct _UIUpdateSequence {
115+
_UIUpdateSequenceItem * _Nullable first;
116+
} _UIUpdateSequence;
117+
118+
typedef struct _UIUpdateSequenceItem {
119+
_UIUpdateSequenceItem * _Nullable next;
120+
_UIUpdateSequence * _Nullable sequence;
121+
const char * name;
122+
uint32_t flags;
123+
void * _Nullable context;
124+
_UIUpdateSequenceCallback _Nullable callback;
125+
} _UIUpdateSequenceItem;
126+
127+
OPENSWIFTUI_EXPORT
128+
_UIUpdateSequenceItem * _Nonnull _UIUpdateSequenceCATransactionCommitItem;
129+
130+
OPENSWIFTUI_EXPORT
131+
void * _Nonnull _UIUpdateSequenceInsertItem(_UIUpdateSequenceItem * _Nullable next,
132+
_UIUpdateSequence * _Nullable sequence,
133+
const char * name,
134+
uint32_t flags,
135+
void * _Nullable context,
136+
_UIUpdateSequenceCallback _Nullable callback);
137+
138+
OPENSWIFTUI_EXPORT
139+
void _UIUpdateSequenceRemoveItem(_UIUpdateSequenceItem *item);
100140

101141
OPENSWIFTUI_ASSUME_NONNULL_END
102142

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//
2+
// UIKitUpdateCycle.swift
3+
// OpenSwiftUI
4+
//
5+
// Audited for 6.5.4
6+
// Status: WIP
7+
// ID: 61722010453917A59567A84BEBF44765 (SwiftUI)
8+
9+
#if os(iOS) || os(visionOS)
10+
import COpenSwiftUI
11+
@_spi(ForOpenSwiftUIOnly)
12+
import OpenSwiftUICore
13+
14+
15+
enum UIKitUpdateCycle {
16+
private static var observerActions: [() -> Void] = []
17+
18+
private static var item: OpaquePointer?
19+
20+
static var defaultUseSetNeedsLayout: Bool = {
21+
let key = "UseSetNeedsLayoutForUpdates"
22+
let defaults = UserDefaults.standard
23+
guard defaults.object(forKey: key) != nil else {
24+
return false
25+
}
26+
return defaults.bool(forKey: key)
27+
}()
28+
29+
static func addPreCommitObserver(_ action: @escaping () -> Void) {
30+
guard _UIUpdateCycleEnabled() else {
31+
return
32+
}
33+
if item == nil {
34+
item = OpaquePointer(
35+
_UIUpdateSequenceInsertItem(
36+
_UIUpdateSequenceCATransactionCommitItem,
37+
nil,
38+
"OpenSwiftUIFlush",
39+
0,
40+
nil,
41+
) { _, _, _ in
42+
let actions = observerActions
43+
guard !actions.isEmpty else { return }
44+
observerActions = []
45+
for action in actions {
46+
Update.perform(action)
47+
}
48+
},
49+
)
50+
51+
}
52+
observerActions.append(action)
53+
}
54+
55+
static func addPreCommitObserverOrAsyncMain(_ action: @escaping () -> Void) {
56+
if _UIUpdateCycleEnabled() {
57+
addPreCommitObserver(action)
58+
} else {
59+
DispatchQueue.main.async(execute: action)
60+
}
61+
}
62+
}
63+
64+
#endif

Sources/OpenSwiftUICore/Data/Update.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ package enum Update {
105105

106106
@inlinable
107107
@inline(__always)
108-
static func perform<T>(_ body: () throws -> T) rethrows -> T {
108+
package static func perform<T>(_ body: () throws -> T) rethrows -> T {
109109
begin()
110110
defer { end() }
111111
return try body()

0 commit comments

Comments
 (0)