Skip to content

Commit 98021d5

Browse files
authored
Add CoreGlue2 (#216)
* Update CoreGlue2 * Update OpenSwiftUIGlue2 * Try to fix flaky macOS CI issue
1 parent a733af3 commit 98021d5

15 files changed

+422
-23
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//
2+
// OpenSwiftUI+UIApplication.h
3+
// COpenSwiftUI
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
8+
#ifndef OpenSwiftUI_UIApplication_h
9+
#define OpenSwiftUI_UIApplication_h
10+
11+
#include "OpenSwiftUIBase.h"
12+
13+
#if OPENSWIFTUI_TARGET_OS_IOS
14+
15+
#import <UIKit/UIKit.h>
16+
17+
OPENSWIFTUI_ASSUME_NONNULL_BEGIN
18+
19+
OPENSWIFTUI_EXPORT
20+
UIContentSizeCategory _UIApplicationDefaultContentSizeCategory();
21+
22+
OPENSWIFTUI_ASSUME_NONNULL_END
23+
24+
#endif /* OPENSWIFTUI_TARGET_OS_IOS */
25+
26+
#endif /* OpenSwiftUI_UIApplication_h */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// OpenSwiftUI+UIApplication.m
3+
// COpenSwiftUI
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
8+
#include "OpenSwiftUI+UIApplication.h"
9+
10+
#if OPENSWIFTUI_TARGET_OS_IOS
11+
#include <objc/runtime.h>
12+
13+
UIContentSizeCategory _UIApplicationDefaultContentSizeCategory() {
14+
typedef UIContentSizeCategory (*Func)(Class, SEL);
15+
SEL selector = NSSelectorFromString(@"_defaultContentSizeCategory");
16+
Func func = nil;
17+
if ([UIApplication resolveClassMethod:selector]) {
18+
IMP impl = class_getMethodImplementation(UIApplication.class, selector);
19+
func = (Func)impl;
20+
}
21+
if (func == nil) {
22+
return UIContentSizeCategoryLarge;
23+
}
24+
return func(UIApplication.class, selector);
25+
}
26+
27+
#endif /* OPENSWIFTUI_TARGET_OS_IOS */

Sources/COpenSwiftUI/UIKit/OpenSwiftUI+UIColor.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ BOOL _UIColorDependsOnTraitCollection(UIColor *color);
2828

2929
OPENSWIFTUI_ASSUME_NONNULL_END
3030

31-
#endif
31+
#endif /* OPENSWIFTUI_TARGET_OS_IOS */
3232

3333
#endif /* OpenSwiftUI_UIColor_h */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//
2+
// OpenSwiftUITesting_Swizzles+UIKit.h
3+
// COpenSwiftUI
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
8+
#ifndef OpenSwiftUITesting_Swizzles_UIKit_h
9+
#define OpenSwiftUITesting_Swizzles_UIKit_h
10+
11+
#include "OpenSwiftUIBase.h"
12+
13+
#if OPENSWIFTUI_TARGET_OS_IOS
14+
#include <UIKit/UIKit.h>
15+
16+
OPENSWIFTUI_ASSUME_NONNULL_BEGIN
17+
18+
@interface UIScreen (OpenSwiftUITesting_Swizzles)
19+
+ (void)_performOpenSwiftUITestingOverrides;
20+
- (CGFloat)_OpenSwiftUITesting_currentScreenScale;
21+
- (BOOL)_OpenSwiftUITesting_wantsWideContentMargins;
22+
@end
23+
24+
@interface UICollectionView (OpenSwiftUITesting_Swizzles)
25+
+ (void)_performOpenSwiftUITestingOverrides;
26+
- (id)_OpenSwiftUITesting__viewAnimationsForCurrentUpdateWithCollectionViewAnimator:(id)arg1;
27+
@end
28+
29+
OPENSWIFTUI_ASSUME_NONNULL_END
30+
31+
#endif /* OPENSWIFTUI_TARGET_OS_IOS */
32+
33+
#endif /* OpenSwiftUITesting_Swizzles_UIKit_h */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// OpenSwiftUITesting_Swizzles+UIKit.m
3+
// COpenSwiftUI
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
8+
#include "OpenSwiftUITesting_Swizzles+UIKit.h"
9+
#include "OpenSwiftUITesting_Swizzles.h"
10+
11+
#if OPENSWIFTUI_TARGET_OS_IOS
12+
13+
@implementation UIScreen (OpenSwiftUITesting_Swizzles)
14+
+ (void)_performOpenSwiftUITestingOverrides {
15+
_SwizzleMethods(UIScreen.class, @selector(scale), @selector(_OpenSwiftUITesting_currentScreenScale));
16+
_SwizzleMethods(UIScreen.class, @selector(_wantsWideContentMargins), @selector(_OpenSwiftUITesting_wantsWideContentMargins));
17+
}
18+
19+
- (CGFloat)_OpenSwiftUITesting_currentScreenScale {
20+
return 2.0;
21+
}
22+
23+
- (BOOL)_OpenSwiftUITesting_wantsWideContentMargins {
24+
return NO;
25+
}
26+
@end
27+
28+
@implementation UICollectionView (OpenSwiftUITesting_Swizzles)
29+
+ (void)_performOpenSwiftUITestingOverrides {
30+
_SwizzleMethods(UIScreen.class, @selector(_viewAnimationsForCurrentUpdateWithCollectionViewAnimator:), @selector(_OpenSwiftUITesting__viewAnimationsForCurrentUpdateWithCollectionViewAnimator:));
31+
}
32+
33+
- (id)_OpenSwiftUITesting__viewAnimationsForCurrentUpdateWithCollectionViewAnimator:(id)arg1 {
34+
return nil;
35+
}
36+
@end
37+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// OpenSwiftUITesting_Swizzles.h
3+
// COpenSwiftUI
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
8+
#ifndef OpenSwiftUITesting_Swizzles_h
9+
#define OpenSwiftUITesting_Swizzles_h
10+
11+
#include "OpenSwiftUIBase.h"
12+
13+
OPENSWIFTUI_ASSUME_NONNULL_BEGIN
14+
15+
#if OPENSWIFTUI_TARGET_OS_IOS
16+
17+
OPENSWIFTUI_EXPORT
18+
void _PerformTestingSwizzles();
19+
20+
OPENSWIFTUI_EXPORT
21+
void _SwizzleMethods(Class class, SEL originalSelector, SEL swizzledSelector);
22+
23+
#endif /* OPENSWIFTUI_TARGET_OS_IOS */
24+
25+
OPENSWIFTUI_ASSUME_NONNULL_END
26+
27+
#endif /* OpenSwiftUITesting_Swizzles_h */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// OpenSwiftUITesting_Swizzles.m
3+
// COpenSwiftUI
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
8+
#include "OpenSwiftUITesting_Swizzles.h"
9+
10+
#if OPENSWIFTUI_TARGET_OS_IOS
11+
#include <objc/runtime.h>
12+
#include "UIKit/OpenSwiftUITesting_Swizzles+UIKit.h"
13+
14+
void _PerformTestingSwizzles() {
15+
static dispatch_once_t onceToken;
16+
dispatch_once(&onceToken, ^{
17+
[UIScreen _performOpenSwiftUITestingOverrides];
18+
[UICollectionView _performOpenSwiftUITestingOverrides];
19+
});
20+
}
21+
22+
void _SwizzleMethods(Class class, SEL originalSelector, SEL swizzledSelector) {
23+
Method originalMethod = class_getInstanceMethod(class, originalSelector);
24+
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
25+
IMP swizzledImp = method_getImplementation(swizzledMethod);
26+
const char *swizzledTypeEncoding = method_getTypeEncoding(swizzledMethod);
27+
BOOL success = class_addMethod(class, originalSelector, swizzledImp, swizzledTypeEncoding);
28+
if (success) {
29+
IMP originalImp = method_getImplementation(originalMethod);
30+
const char *originalTypeEncoding = method_getTypeEncoding(originalMethod);
31+
class_replaceMethod(class, swizzledSelector, originalImp, originalTypeEncoding);
32+
} else {
33+
method_exchangeImplementations(originalMethod, swizzledMethod);
34+
}
35+
}
36+
37+
#endif /* OPENSWIFTUI_TARGET_OS_IOS */

Sources/OpenSwiftUI/CoreGlue/OpenSwiftUIGlue.swift

+71-4
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,94 @@
33
// OpenSwiftUI
44
//
55
// Audited for iOS 18.0
6-
// Status: Empty
6+
// Status: WIP
77

88
@_spi(ForOpenSwiftUIOnly)
99
public import OpenSwiftUICore
10+
import COpenSwiftUI
1011

1112
#if canImport(Darwin)
1213

14+
public import Foundation
15+
1316
@_spi(ForOpenSwiftUIOnly)
1417
@_silgen_name("OpenSwiftUIGlueClass")
1518
public func OpenSwiftUIGlueClass() -> CoreGlue.Type {
1619
OpenSwiftUIGlue.self
1720
}
1821

19-
final class OpenSwiftUIGlue: CoreGlue {
20-
override var defaultImplicitRootType: DefaultImplicitRootTypeResult {
22+
@_spi(ForOpenSwiftUIOnly)
23+
@objc(OpenSwiftUIGlue)
24+
final public class OpenSwiftUIGlue: CoreGlue {
25+
override final public var defaultImplicitRootType: DefaultImplicitRootTypeResult {
2126
DefaultImplicitRootTypeResult(_VStackLayout.self)
2227
}
2328

24-
override func makeDefaultLayoutComputer() -> MakeDefaultLayoutComputerResult {
29+
override final public func makeDefaultLayoutComputer() -> MakeDefaultLayoutComputerResult {
2530
MakeDefaultLayoutComputerResult(value: ViewGraph.current.$defaultLayoutComputer)
2631
}
2732
}
2833

34+
@_spi(ForOpenSwiftUIOnly)
35+
@available(*, unavailable)
36+
extension OpenSwiftUIGlue: Sendable {}
37+
38+
@_spi(ForOpenSwiftUIOnly)
39+
@_silgen_name("OpenSwiftUIGlue2Class")
40+
public func OpenSwiftUIGlue2Class() -> CoreGlue2.Type {
41+
OpenSwiftUIGlue2.self
42+
}
43+
44+
@_spi(ForOpenSwiftUIOnly)
45+
@objc(OpenSwiftUIGlue2)
46+
final public class OpenSwiftUIGlue2: CoreGlue2 {
47+
#if os(iOS)
48+
override public final func initializeTestApp() {
49+
_PerformTestingSwizzles()
50+
}
51+
#endif
52+
53+
override public final func isStatusBarHidden() -> Bool? {
54+
#if os(iOS)
55+
guard let scene = UIApplication.shared.connectedScenes.first,
56+
let windowScene = scene as? UIWindowScene
57+
else {
58+
return nil
59+
}
60+
return windowScene.statusBarManager?.isStatusBarHidden ?? false
61+
#else
62+
nil
63+
#endif
64+
}
65+
66+
override public final func configureDefaultEnvironment(_: inout EnvironmentValues) {
67+
}
68+
69+
override public final func makeRootView(base: AnyView, rootFocusScope: Namespace.ID) -> AnyView {
70+
AnyView(base.safeAreaInsets(.zero, next: nil))
71+
}
72+
73+
override public final var systemDefaultDynamicTypeSize: DynamicTypeSize {
74+
#if os(iOS)
75+
let size = _UIApplicationDefaultContentSizeCategory()
76+
let dynamicSize = DynamicTypeSize(size)
77+
return dynamicSize ?? .large
78+
#else
79+
// TODO: macOS
80+
return .large
81+
#endif
82+
}
83+
84+
override public final var codableAttachmentCellType: CodableAttachmentCellTypeResult {
85+
CodableAttachmentCellTypeResult(nil)
86+
}
87+
88+
override public final func linkURL(_ parameters: LinkURLParameters) -> URL? {
89+
preconditionFailure("TODO")
90+
}
91+
}
92+
93+
@_spi(ForOpenSwiftUIOnly)
94+
@available(*, unavailable)
95+
extension OpenSwiftUIGlue2: Sendable {}
2996
#endif

Sources/OpenSwiftUI/Integration/Graphic/UIKit/OpenSwiftUI+UIColor.swift renamed to Sources/OpenSwiftUI/Integration/Graphic/UIKit/UIKitConversions.swift

+38-7
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
//
2-
// OpenSwiftUI+UIKit.swift
2+
// UIKitConversions.swift
33
// OpenSwiftUI
44
//
55
// Audited for iOS 18.0
66
// Status: WIP
7-
// ID: 6DC24D5146AF4B80347A1025025F68EE (SwiftUI?)
7+
// ID: 6DC24D5146AF4B80347A1025025F68EE (SwiftUI)
88

99
#if canImport(UIKit)
1010

1111
public import OpenSwiftUICore
1212
public import UIKit
1313
import COpenSwiftUI
1414

15-
// MARK: - Color + UIColor
15+
// MARK: - UIColor Conversions
1616

1717
@available(*, deprecated, message: "Use Color(uiColor:) when converting a UIColor, or create a standard Color directly")
1818
@available(macOS, unavailable)
@@ -146,11 +146,13 @@ extension UIColor: ColorProvider {
146146
}
147147
}
148148

149-
public extension ColorScheme {
149+
// MARK: - UIUserInterfaceStyle Conversions
150+
151+
extension ColorScheme {
150152
/// Creates a color scheme from its user interface style equivalent.
151153
@available(macOS, unavailable)
152154
@available(watchOS, unavailable)
153-
init?(_ uiUserInterfaceStyle: UIUserInterfaceStyle) {
155+
public init?(_ uiUserInterfaceStyle: UIUserInterfaceStyle) {
154156
switch uiUserInterfaceStyle {
155157
case .unspecified: return nil
156158
case .light: self = .light
@@ -160,16 +162,45 @@ public extension ColorScheme {
160162
}
161163
}
162164

163-
public extension UIUserInterfaceStyle {
165+
extension UIUserInterfaceStyle {
164166
/// Creates a user interface style from its ColorScheme equivalent.
165167
@available(macOS, unavailable)
166168
@available(watchOS, unavailable)
167-
init(_ colorScheme: ColorScheme?) {
169+
public init(_ colorScheme: ColorScheme?) {
168170
switch colorScheme {
169171
case .light: self = .light
170172
case .dark: self = .dark
171173
case nil: self = .unspecified
172174
}
173175
}
174176
}
177+
178+
// MARK: - UIAccessibilityContrast Conversions [TODO]
179+
180+
// ColorSchemeContrast
181+
// UIAccessibilityContrast
182+
183+
// MARK: - UIContentSizeCategory Conversions [WIP]
184+
185+
extension DynamicTypeSize {
186+
/// Create a Dynamic Type size from its `UIContentSizeCategory` equivalent.
187+
public init?(_ uiSizeCategory: UIContentSizeCategory) {
188+
switch uiSizeCategory {
189+
case .extraSmall: self = .xSmall
190+
case .small: self = .small
191+
case .medium: self = .medium
192+
case .large: self = .large
193+
case .extraLarge: self = .xLarge
194+
case .extraExtraLarge: self = .xxLarge
195+
case .extraExtraExtraLarge: self = .xxxLarge
196+
case .accessibilityMedium: self = .accessibility1
197+
case .accessibilityLarge: self = .accessibility2
198+
case .accessibilityExtraLarge: self = .accessibility3
199+
case .accessibilityExtraExtraLarge: self = .accessibility4
200+
case .accessibilityExtraExtraExtraLarge: self = .accessibility5
201+
default: return nil
202+
}
203+
}
204+
}
205+
175206
#endif

0 commit comments

Comments
 (0)