未验证 提交 a832502e 编写于 作者: C chunhtai 提交者: GitHub

Fixes iOS refuses to accept semantics rect update if UISwitch is not … (#26416)

* Fixes iOS refuses to accept semantics rect update if UISwitch is not in the view

* update
上级 a048b8da
...@@ -149,11 +149,10 @@ constexpr int32_t kRootNodeId = 0; ...@@ -149,11 +149,10 @@ constexpr int32_t kRootNodeId = 0;
@end @end
/// A proxy class for SemanticsObject and UISwitch. For most Accessibility and /// The semantics object for switch buttons. This class creates an UISwitch to interact with the
/// SemanticsObject methods it delegates to the semantics object, otherwise it /// iOS.
/// sends messages to the UISwitch. @interface FlutterSwitchSemanticsObject : SemanticsObject
@interface FlutterSwitchSemanticsObject : UISwitch
- (instancetype)initWithSemanticsObject:(SemanticsObject*)semanticsObject;
@end @end
/** /**
......
...@@ -37,96 +37,53 @@ flutter::SemanticsAction GetSemanticsActionForScrollDirection( ...@@ -37,96 +37,53 @@ flutter::SemanticsAction GetSemanticsActionForScrollDirection(
} // namespace } // namespace
@implementation FlutterSwitchSemanticsObject { @implementation FlutterSwitchSemanticsObject {
SemanticsObject* _semanticsObject; UISwitch* _nativeSwitch;
} }
- (instancetype)initWithSemanticsObject:(SemanticsObject*)semanticsObject { - (instancetype)initWithBridge:(fml::WeakPtr<flutter::AccessibilityBridgeIos>)bridge
self = [super init]; uid:(int32_t)uid {
self = [super initWithBridge:bridge uid:uid];
if (self) { if (self) {
_semanticsObject = [semanticsObject retain]; _nativeSwitch = [[[UISwitch alloc] init] retain];
} }
return self; return self;
} }
- (void)dealloc { - (void)dealloc {
[_semanticsObject release]; [_nativeSwitch release];
[super dealloc]; [super dealloc];
} }
- (NSMethodSignature*)methodSignatureForSelector:(SEL)sel { - (NSMethodSignature*)methodSignatureForSelector:(SEL)sel {
NSMethodSignature* result = [super methodSignatureForSelector:sel]; NSMethodSignature* result = [super methodSignatureForSelector:sel];
if (!result) { if (!result) {
result = [_semanticsObject methodSignatureForSelector:sel]; result = [_nativeSwitch methodSignatureForSelector:sel];
} }
return result; return result;
} }
- (void)forwardInvocation:(NSInvocation*)anInvocation { - (void)forwardInvocation:(NSInvocation*)anInvocation {
[anInvocation setTarget:_semanticsObject]; [anInvocation setTarget:_nativeSwitch];
[anInvocation invoke]; [anInvocation invoke];
} }
// The following methods are explicitly forwarded to the wrapped SemanticsObject because the
// forwarding logic above doesn't apply to them since they are also implemented in the UISwitch
// class, the base class.
- (CGRect)accessibilityFrame {
return [_semanticsObject accessibilityFrame];
}
- (id)accessibilityContainer {
return [_semanticsObject accessibilityContainer];
}
- (NSString*)accessibilityLabel {
return [_semanticsObject accessibilityLabel];
}
- (NSString*)accessibilityHint {
return [_semanticsObject accessibilityHint];
}
- (NSString*)accessibilityValue { - (NSString*)accessibilityValue {
if ([_semanticsObject node].HasFlag(flutter::SemanticsFlags::kIsToggled) || if ([self node].HasFlag(flutter::SemanticsFlags::kIsToggled) ||
[_semanticsObject node].HasFlag(flutter::SemanticsFlags::kIsChecked)) { [self node].HasFlag(flutter::SemanticsFlags::kIsChecked)) {
self.on = YES; _nativeSwitch.on = YES;
} else { } else {
self.on = NO; _nativeSwitch.on = NO;
} }
if (![_semanticsObject isAccessibilityBridgeAlive]) { if (![self isAccessibilityBridgeAlive]) {
return nil; return nil;
} else { } else {
return [super accessibilityValue]; return _nativeSwitch.accessibilityValue;
} }
} }
- (BOOL)accessibilityActivate { - (UIAccessibilityTraits)accessibilityTraits {
return [_semanticsObject accessibilityActivate]; return _nativeSwitch.accessibilityTraits;
}
- (void)accessibilityIncrement {
[_semanticsObject accessibilityIncrement];
}
- (void)accessibilityDecrement {
[_semanticsObject accessibilityDecrement];
}
- (BOOL)accessibilityScroll:(UIAccessibilityScrollDirection)direction {
return [_semanticsObject accessibilityScroll:direction];
}
- (BOOL)accessibilityPerformEscape {
return [_semanticsObject accessibilityPerformEscape];
}
- (void)accessibilityElementDidBecomeFocused {
[_semanticsObject accessibilityElementDidBecomeFocused];
}
- (void)accessibilityElementDidLoseFocus {
[_semanticsObject accessibilityElementDidLoseFocus];
} }
@end // FlutterSwitchSemanticsObject @end // FlutterSwitchSemanticsObject
......
...@@ -252,35 +252,36 @@ class MockAccessibilityBridge : public AccessibilityBridgeIos { ...@@ -252,35 +252,36 @@ class MockAccessibilityBridge : public AccessibilityBridgeIos {
XCTAssertNil(weakObject); XCTAssertNil(weakObject);
} }
- (void)testFlutterSwitchSemanticsObjectForwardsCalls { - (void)testFlutterSwitchSemanticsObjectMatchesUISwitch {
SemanticsObject* mockSemanticsObject = OCMClassMock([SemanticsObject class]); fml::WeakPtrFactory<flutter::MockAccessibilityBridge> factory(
FlutterSwitchSemanticsObject* switchObj = new flutter::MockAccessibilityBridge());
[[FlutterSwitchSemanticsObject alloc] initWithSemanticsObject:mockSemanticsObject]; fml::WeakPtr<flutter::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
OCMStub([mockSemanticsObject accessibilityActivate]).andReturn(YES); FlutterSwitchSemanticsObject* object = [[FlutterSwitchSemanticsObject alloc] initWithBridge:bridge
OCMStub([mockSemanticsObject accessibilityScroll:UIAccessibilityScrollDirectionRight]) uid:1];
.andReturn(NO);
OCMStub([mockSemanticsObject accessibilityPerformEscape]).andReturn(YES);
XCTAssertTrue([switchObj accessibilityActivate]);
OCMVerify([mockSemanticsObject accessibilityActivate]);
[switchObj accessibilityIncrement];
OCMVerify([mockSemanticsObject accessibilityIncrement]);
[switchObj accessibilityDecrement]; // Handle initial setting of node with header.
OCMVerify([mockSemanticsObject accessibilityDecrement]); flutter::SemanticsNode node;
node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasToggledState) |
static_cast<int32_t>(flutter::SemanticsFlags::kIsToggled);
node.label = "foo";
[object setSemanticsNode:&node];
// Create ab real UISwitch to compare the FlutterSwitchSemanticsObject with.
UISwitch* nativeSwitch = [[UISwitch alloc] init];
nativeSwitch.on = YES;
XCTAssertFalse([switchObj accessibilityScroll:UIAccessibilityScrollDirectionRight]); XCTAssertEqual(object.accessibilityTraits, nativeSwitch.accessibilityTraits);
OCMVerify([mockSemanticsObject accessibilityScroll:UIAccessibilityScrollDirectionRight]); XCTAssertEqual(object.accessibilityValue, nativeSwitch.accessibilityValue);
XCTAssertTrue([switchObj accessibilityPerformEscape]); // Set the toggled to false;
OCMVerify([mockSemanticsObject accessibilityPerformEscape]); flutter::SemanticsNode update;
update.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasToggledState);
update.label = "foo";
[object setSemanticsNode:&update];
[switchObj accessibilityElementDidBecomeFocused]; nativeSwitch.on = NO;
OCMVerify([mockSemanticsObject accessibilityElementDidBecomeFocused]);
[switchObj accessibilityElementDidLoseFocus]; XCTAssertEqual(object.accessibilityTraits, nativeSwitch.accessibilityTraits);
OCMVerify([mockSemanticsObject accessibilityElementDidLoseFocus]); XCTAssertEqual(object.accessibilityValue, nativeSwitch.accessibilityValue);
} }
@end @end
...@@ -257,10 +257,7 @@ static SemanticsObject* CreateObject(const flutter::SemanticsNode& node, ...@@ -257,10 +257,7 @@ static SemanticsObject* CreateObject(const flutter::SemanticsNode& node,
return [[[TextInputSemanticsObject alloc] initWithBridge:weak_ptr uid:node.id] autorelease]; return [[[TextInputSemanticsObject alloc] initWithBridge:weak_ptr uid:node.id] autorelease];
} else if (node.HasFlag(flutter::SemanticsFlags::kHasToggledState) || } else if (node.HasFlag(flutter::SemanticsFlags::kHasToggledState) ||
node.HasFlag(flutter::SemanticsFlags::kHasCheckedState)) { node.HasFlag(flutter::SemanticsFlags::kHasCheckedState)) {
SemanticsObject* delegateObject = return [[[FlutterSwitchSemanticsObject alloc] initWithBridge:weak_ptr uid:node.id] autorelease];
[[[FlutterSemanticsObject alloc] initWithBridge:weak_ptr uid:node.id] autorelease];
return (SemanticsObject*)[[[FlutterSwitchSemanticsObject alloc]
initWithSemanticsObject:delegateObject] autorelease];
} else { } else {
return [[[FlutterSemanticsObject alloc] initWithBridge:weak_ptr uid:node.id] autorelease]; return [[[FlutterSemanticsObject alloc] initWithBridge:weak_ptr uid:node.id] autorelease];
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册