Skip to content

Commit 2a2aed8

Browse files
authored
Update OpenSwiftUIShims for Darwin (#274)
* Update UIKit_Private * Add OpenSwiftUIShims * Update new UIView & CALayer private API * Add test case for UIKit and CA private API * Update AppKit API
1 parent b189546 commit 2a2aed8

File tree

12 files changed

+248
-59
lines changed

12 files changed

+248
-59
lines changed

Sources/OpenSwiftUI/Integration/Render/UIKit/UIViewPlatformViewDefinition.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,18 @@ final class UIViewPlatformViewDefinition: PlatformViewDefinition, @unchecked Sen
5252
if kind != .platformView && kind != .platformGroup {
5353
view.autoresizesSubviews = false
5454
if !kind.isContainer {
55-
// view._setFocusInteractionEnabled = false
55+
view._setFocusInteractionEnabled(false)
5656
}
5757
}
5858
view.layer.anchorPoint = .zero
5959
switch kind {
6060
case .color, .image, .shape:
61-
// view.layer.setAllowsEdgeAntialiasing = true
61+
view.layer.setAllowsEdgeAntialiasing(true)
6262
break
6363
case .geometry, .projection, .affine3D, .mask, .platformEffect:
64-
// view.layer.setAllowsGroupOpacity = false
65-
// view.layer.setAllowsGroupBlending = false
64+
let layer = view.layer
65+
layer.setAllowsGroupOpacity(false)
66+
layer.setAllowsGroupBlending(false)
6667
break
6768
default:
6869
break

Sources/OpenSwiftUI_SPI/Shims/AppKit/AppKit_Private.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
OPENSWIFTUI_ASSUME_NONNULL_BEGIN
1717

1818
@interface NSApplication (OpenSwiftUI_SPI)
19-
- (void)startedTest:(nullable NSString *)name;
20-
- (void)finishedTest:(nullable NSString *)name;
21-
- (void)failedTest:(nullable NSString *)name withFailure:(nullable NSError*)failure;
19+
- (void)startedTest_openswiftui_safe_wrapper:(nullable NSString *)name OPENSWIFTUI_SWIFT_NAME(startedTest(_:));
20+
- (void)finishedTest_openswiftui_safe_wrapper:(nullable NSString *)name OPENSWIFTUI_SWIFT_NAME(finishedTest(_:));
21+
- (void)failedTest_openswiftui_safe_wrapper:(nullable NSString *)name withFailure:(nullable NSError*)failure OPENSWIFTUI_SWIFT_NAME(failedTest(_:withFailure:));
2222
@end
2323

2424
OPENSWIFTUI_ASSUME_NONNULL_END

Sources/OpenSwiftUI_SPI/Shims/AppKit/AppKit_Private.m

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,28 @@
55
// Status: WIP
66

77
#import "AppKit_Private.h"
8+
#import "../OpenSwiftUIShims.h"
9+
10+
#if __has_include(<AppKit/AppKit.h>)
11+
12+
#import <objc/runtime.h>
13+
14+
@implementation NSApplication (OpenSwiftUI_SPI)
15+
- (void)startedTest_openswiftui_safe_wrapper:(NSString *)name {
16+
OPENSWIFTUI_SAFE_WRAPPER_IMP(void, @"startedTest:", , NSString *);
17+
func(self, selector, name);
18+
}
19+
20+
- (void)finishedTest_openswiftui_safe_wrapper:(NSString *)name {
21+
OPENSWIFTUI_SAFE_WRAPPER_IMP(void, @"finishedTest:", , NSString *);
22+
func(self, selector, name);
23+
}
24+
25+
- (void)failedTest_openswiftui_safe_wrapper:(NSString *)name withFailure:(NSError *)failure {
26+
OPENSWIFTUI_SAFE_WRAPPER_IMP(void, @"failedTest:withFailure:", , NSString *, NSError *);
27+
func(self, selector, name, failure);
28+
}
29+
@end
30+
31+
#endif /* AppKit.h */
832

Sources/OpenSwiftUI_SPI/Shims/CoreAnimation/CoreAnimation_Private.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@
1414
OPENSWIFTUI_ASSUME_NONNULL_BEGIN
1515

1616
@interface CALayer (OpenSwiftUI_SPI)
17-
@property (nonatomic, assign, readonly) BOOL openSwiftUI_hasBeenCommitted OPENSWIFTUI_SWIFT_NAME(hasBeenCommitted);
17+
@property (nonatomic, assign, readonly) BOOL hasBeenCommitted_openswiftui_safe_wrapper OPENSWIFTUI_SWIFT_NAME(hasBeenCommitted);
18+
- (void)setAllowsEdgeAntialiasing_openswiftui_safe_wrapper:(BOOL)allows OPENSWIFTUI_SWIFT_NAME(setAllowsEdgeAntialiasing(_:));
19+
- (void)setAllowsGroupOpacity_openswiftui_safe_wrapper:(BOOL)allows OPENSWIFTUI_SWIFT_NAME(setAllowsGroupOpacity(_:));
20+
- (void)setAllowsGroupBlending_openswiftui_safe_wrapper:(BOOL)allows OPENSWIFTUI_SWIFT_NAME(setAllowsGroupBlending(_:));
21+
1822
@property (nonatomic, assign) uint64_t openSwiftUI_viewTestProperties;
1923
@end
2024

Sources/OpenSwiftUI_SPI/Shims/CoreAnimation/CoreAnimation_Private.m

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,52 +6,39 @@
66

77
#if __has_include(<QuartzCore/CoreAnimation.h>)
88

9+
#import "../OpenSwiftUIShims.h"
910
#import <objc/runtime.h>
1011

1112
@implementation CALayer (OpenSwiftUI_SPI)
1213

13-
- (BOOL)openSwiftUI_hasBeenCommitted {
14-
typedef BOOL (*Func)(CALayer *, SEL);
15-
SEL selector = NSSelectorFromString(@"hasBeenCommitted");
16-
Func func = nil;
17-
if ([self respondsToSelector:selector]) {
18-
IMP impl = class_getMethodImplementation([self class], selector);
19-
func = (Func)impl;
20-
}
21-
if (func == nil) {
22-
return NO;
23-
}
14+
- (BOOL)hasBeenCommitted_openswiftui_safe_wrapper {
15+
OPENSWIFTUI_SAFE_WRAPPER_IMP(BOOL, @"hasBeenCommitted", NO);
2416
return func(self, selector);
2517
}
2618

27-
- (uint64_t)openSwiftUI_viewTestProperties {
28-
typedef uint64_t (*Func)(CALayer *, SEL);
29-
SEL selector = NSSelectorFromString(@"swiftUI_viewTestProperties");
30-
Func func = nil;
31-
if ([self respondsToSelector:selector]) {
32-
IMP impl = class_getMethodImplementation([self class], selector);
33-
func = (Func)impl;
34-
}
35-
if (func == nil) {
36-
return 0;
37-
}
38-
return func(self, selector);
19+
- (void)setAllowsEdgeAntialiasing_openswiftui_safe_wrapper:(BOOL)allows {
20+
OPENSWIFTUI_SAFE_WRAPPER_IMP(void, @"setAllowsEdgeAntialiasing:", , BOOL);
21+
func(self, selector, allows);
22+
}
23+
24+
- (void)setAllowsGroupOpacity_openswiftui_safe_wrapper:(BOOL)allows {
25+
OPENSWIFTUI_SAFE_WRAPPER_IMP(void, @"setAllowsGroupOpacity:", , BOOL);
26+
func(self, selector, allows);
3927
}
4028

41-
- (void)setOpenSwiftUI_viewTestProperties:(uint64_t)viewTestProperties {
42-
typedef void (*Func)(CALayer *, SEL, uint64_t);
43-
SEL selector = NSSelectorFromString(@"setSwiftUI_viewTestProperties:");
44-
Func func = nil;
45-
if ([self respondsToSelector:selector]) {
46-
IMP impl = class_getMethodImplementation([self class], selector);
47-
func = (Func)impl;
48-
}
49-
if (func == nil) {
50-
return;
51-
}
52-
return func(self, selector, viewTestProperties);
29+
- (void)setAllowsGroupBlending_openswiftui_safe_wrapper:(BOOL)allows {
30+
OPENSWIFTUI_SAFE_WRAPPER_IMP(void, @"setAllowsGroupBlending:", , BOOL);
31+
func(self, selector, allows);
5332
}
5433

34+
- (uint64_t)openSwiftUI_viewTestProperties {
35+
NSNumber *properties = [self valueForKey:@"_viewTestProperties"];
36+
return properties.integerValue;
37+
}
38+
39+
- (void)setOpenSwiftUI_viewTestProperties:(uint64_t)properties {
40+
[self setValue:[NSNumber numberWithUnsignedLongLong:properties] forKey:@"_viewTestProperties"];
41+
}
5542
@end
5643

5744
#endif /* CoreAnimation.h */
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// OpenSwiftUIShims.h
3+
// OpenSwiftUI_SPI
4+
//
5+
6+
#ifndef OpenSwiftUIShims_h
7+
#define OpenSwiftUIShims_h
8+
9+
#include "OpenSwiftUIBase.h"
10+
11+
#if OPENSWIFTUI_TARGET_OS_DARWIN
12+
13+
#include <os/log.h>
14+
15+
OPENSWIFTUI_ASSUME_NONNULL_BEGIN
16+
17+
OPENSWIFTUI_EXPORT
18+
os_log_t openSwiftUIShimsLog(void);
19+
20+
#define OPENSWIFTUI_SHIMS_LOG_ERROR(fmt, ...) os_log_error(openSwiftUIShimsLog(), fmt, ##__VA_ARGS__)
21+
22+
#define OPENSWIFTUI_SAFE_WRAPPER_IMP(ReturnType, SelectorName, DefaultReturnValue, ...) \
23+
typedef ReturnType (*Func)(id, SEL, ##__VA_ARGS__); \
24+
SEL selector = NSSelectorFromString(SelectorName); \
25+
Func func = nil; \
26+
if ([self respondsToSelector:selector]) { \
27+
IMP impl = class_getMethodImplementation([self class], selector); \
28+
func = (Func)impl; \
29+
} else { \
30+
OPENSWIFTUI_SHIMS_LOG_ERROR("%@ can't respond to selector %@", NSStringFromClass([self class]), NSStringFromSelector(selector)); \
31+
} \
32+
if (func == nil) { \
33+
OPENSWIFTUI_SHIMS_LOG_ERROR("%@ can't get method implementation for selector %@", NSStringFromClass([self class]), NSStringFromSelector(selector)); \
34+
return DefaultReturnValue; \
35+
}
36+
37+
38+
OPENSWIFTUI_ASSUME_NONNULL_END
39+
40+
#endif /* OPENSWIFTUI_TARGET_OS_DARWIN */
41+
42+
#endif /* OpenSwiftUIShims_h */
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//
2+
// OpenSwiftUIShims.m
3+
// OpenSwiftUI_SPI
4+
//
5+
6+
#import "OpenSwiftUIShims.h"
7+
8+
#if OPENSWIFTUI_TARGET_OS_DARWIN
9+
10+
os_log_t openSwiftUIShimsLog(void) {
11+
static dispatch_once_t onceToken;
12+
static os_log_t log = NULL;
13+
dispatch_once(&onceToken, ^{
14+
log = os_log_create("org.OpenSwiftUIProject.OpenSwiftUI", "Shims");
15+
});
16+
return log;
17+
}
18+
19+
#endif /* OPENSWIFTUI_TARGET_OS_DARWIN */

Sources/OpenSwiftUI_SPI/Shims/UIKit/UIKit_Private.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,21 @@ OPENSWIFTUI_ASSUME_NONNULL_BEGIN
1717

1818
@interface UIApplication (OpenSwiftUI_SPI)
1919
// Test API
20-
- (void)startedTest:(nullable NSString *)name;
21-
- (void)finishedTest:(nullable NSString *)name;
22-
- (void)failedTest:(nullable NSString *)name withFailure:(nullable NSError*)failure;
23-
- (nullable NSString *)_launchTestName;
20+
- (void)startedTest_openswiftui_safe_wrapper:(nullable NSString *)name OPENSWIFTUI_SWIFT_NAME(startedTest(_:));
21+
- (void)finishedTest_openswiftui_safe_wrapper:(nullable NSString *)name OPENSWIFTUI_SWIFT_NAME(finishedTest(_:));
22+
- (void)failedTest_openswiftui_safe_wrapper:(nullable NSString *)name withFailure:(nullable NSError*)failure OPENSWIFTUI_SWIFT_NAME(failedTest(_:withFailure:));
23+
- (nullable NSString *)_launchTestName_openswiftui_safe_wrapper OPENSWIFTUI_SWIFT_NAME(_launchTestName());
2424

2525
- (void)_performBlockAfterCATransactionCommits_openswiftui_safe_wrapper:(void (^)(void))block OPENSWIFTUI_SWIFT_NAME(_performBlockAfterCATransactionCommits(_:));
2626
@end
2727

2828
@interface UIView (OpenSwiftUI_SPI)
29-
- (BOOL)_shouldAnimatePropertyWithKey:(NSString *)key;
29+
- (BOOL)_shouldAnimatePropertyWithKey_openswiftui_safe_wrapper:(NSString *)key OPENSWIFTUI_SWIFT_NAME(_shouldAnimateProperty(withKey:));
30+
- (void)_setFocusInteractionEnabled_openswiftui_safe_wrapper:(BOOL)enabled OPENSWIFTUI_SWIFT_NAME(_setFocusInteractionEnabled(_:));
3031
@end
3132

3233
@interface UIViewController (OpenSwiftUI_SPI)
33-
@property (nonatomic, readonly) BOOL _canShowWhileLocked;
34+
@property (nonatomic, readonly) BOOL _canShowWhileLocked_openswiftui_safe_wrapper OPENSWIFTUI_SWIFT_NAME(_canShowWhileLocked);
3435
@end
3536

3637
OPENSWIFTUI_EXPORT

Sources/OpenSwiftUI_SPI/Shims/UIKit/UIKit_Private.m

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,55 @@
55
// Status: WIP
66

77
#import "UIKit_Private.h"
8+
#import "../OpenSwiftUIShims.h"
89

910
#if __has_include(<UIKit/UIKit.h>)
1011

1112
#import <objc/runtime.h>
1213

1314
@implementation UIApplication (OpenSwiftUI_SPI)
1415
- (void)_performBlockAfterCATransactionCommits_openswiftui_safe_wrapper:(void (^)(void))block {
15-
typedef void (*Func)(UIApplication *, SEL, void (^)(void));
16-
SEL selector = NSSelectorFromString(@"_performBlockAfterCATransactionCommits:");
17-
Func func = nil;
18-
if ([self respondsToSelector:selector]) {
19-
IMP impl = class_getMethodImplementation([self class], selector);
20-
func = (Func)impl;
21-
}
22-
if (func != nil) {
23-
func(self, selector, block);
24-
}
16+
OPENSWIFTUI_SAFE_WRAPPER_IMP(void, @"_performBlockAfterCATransactionCommits:", block(),void (^)(void));
17+
func(self, selector, block);
18+
}
19+
20+
- (void)startedTest_openswiftui_safe_wrapper:(NSString *)name {
21+
OPENSWIFTUI_SAFE_WRAPPER_IMP(void, @"startedTest:", , NSString *);
22+
func(self, selector, name);
23+
}
24+
25+
- (void)finishedTest_openswiftui_safe_wrapper:(NSString *)name {
26+
OPENSWIFTUI_SAFE_WRAPPER_IMP(void, @"finishedTest:", , NSString *);
27+
func(self, selector, name);
28+
}
29+
30+
- (void)failedTest_openswiftui_safe_wrapper:(NSString *)name withFailure:(NSError *)failure {
31+
OPENSWIFTUI_SAFE_WRAPPER_IMP(void, @"failedTest:withFailure:", , NSString *, NSError *);
32+
func(self, selector, name, failure);
33+
}
34+
35+
- (NSString *)_launchTestName_openswiftui_safe_wrapper {
36+
OPENSWIFTUI_SAFE_WRAPPER_IMP(NSString *, @"_launchTestName", nil);
37+
return func(self, selector);
38+
}
39+
@end
40+
41+
@implementation UIView (OpenSwiftUI_SPI)
42+
- (BOOL)_shouldAnimatePropertyWithKey_openswiftui_safe_wrapper:(NSString *)key {
43+
OPENSWIFTUI_SAFE_WRAPPER_IMP(BOOL, @"_shouldAnimatePropertyWithKey:", NO, NSString *);
44+
return func(self, selector, key);
45+
}
46+
47+
- (void)_setFocusInteractionEnabled_openswiftui_safe_wrapper:(BOOL)enabled {
48+
OPENSWIFTUI_SAFE_WRAPPER_IMP(void, @"_setFocusInteractionEnabled:", , BOOL);
49+
func(self, selector, enabled);
50+
}
51+
@end
52+
53+
@implementation UIViewController (OpenSwiftUI_SPI)
54+
- (BOOL)_canShowWhileLocked_openswiftui_safe_wrapper {
55+
OPENSWIFTUI_SAFE_WRAPPER_IMP(BOOL, @"_canShowWhileLocked", NO);
56+
return func(self, selector);
2557
}
2658
@end
2759

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//
2+
// AppKitPrivateTests.swift
3+
// OpenSwiftUI_SPITests
4+
5+
import OpenSwiftUI_SPI
6+
import Testing
7+
8+
#if canImport(AppKit)
9+
@MainActor
10+
struct AppKitPrivateTests {
11+
@Test
12+
func application() {
13+
let app = NSApplication.shared
14+
let name = "ATest"
15+
app.startedTest(name)
16+
app.finishedTest(name)
17+
app.failedTest(name, withFailure: nil)
18+
}
19+
}
20+
#endif
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// CoreAnimationPrivateTests.swift
3+
// OpenSwiftUI_SPITests
4+
5+
import OpenSwiftUI_SPI
6+
import Testing
7+
8+
#if canImport(QuartzCore)
9+
@MainActor
10+
struct CoreAnimationPrivateTests {
11+
@Test
12+
func layer() {
13+
let layer = CALayer()
14+
#expect(layer.hasBeenCommitted == false)
15+
layer.setAllowsEdgeAntialiasing(true)
16+
layer.setAllowsGroupOpacity(true)
17+
layer.setAllowsGroupBlending(true)
18+
19+
layer.openSwiftUI_viewTestProperties = 42
20+
#expect(layer.openSwiftUI_viewTestProperties == 42)
21+
}
22+
}
23+
#endif
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// UIKitPrivateTests.swift
3+
// OpenSwiftUI_SPITests
4+
5+
import OpenSwiftUI_SPI
6+
import Testing
7+
8+
#if canImport(UIKit)
9+
@MainActor
10+
struct UIKitPrivateTests {
11+
@Test
12+
func application() {
13+
let app = UIApplication.shared
14+
let name = "ATest"
15+
app.startedTest(name)
16+
app.finishedTest(name)
17+
app.failedTest(name, withFailure: nil)
18+
#expect(app._launchTestName() == nil)
19+
}
20+
21+
@Test
22+
func view() {
23+
let view = UIView()
24+
#expect(view._shouldAnimateProperty(withKey: "frame") == false)
25+
#expect(view._shouldAnimateProperty(withKey: "alpha") == false)
26+
27+
view._setFocusInteractionEnabled(true)
28+
}
29+
30+
@Test
31+
func viewController() {
32+
let controller = UIViewController()
33+
#expect(controller._canShowWhileLocked == true)
34+
}
35+
}
36+
#endif

0 commit comments

Comments
 (0)