I created a new single view project and added this code to create a UITableView.
- (void)viewDidLoad {
[super viewDidLoad];
tableView=[[UITableView alloc]init];
tableView.frame = CGRectMake(10,30,320,400);
tableView.dataSource=self;
tableView.delegate=self;
tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
[tableView reloadData];
[self.view addSubview:tableView];
}
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath] ;
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = @"hello";
cell.textLabel.accessibilityIdentifier = @"world";
return cell;
}
My UI test simply prints the view hierarchy with print(app.debugDescription)
and as you can see the graph for the main window has 2 leaf views: a StaticText
corresponding to cell.textLabel
and an unidentified/random Other
view. I've tried many ways to figure out what this Other
view is but the answer eludes me.
Element subtree:
→Application, 0x600000d98820, pid: 17292, label: 'TestApp'
Window (Main), 0x600000d989c0, {{0.0, 0.0}, {768.0, 1024.0}}
Other, 0x600000d98a90, {{0.0, 0.0}, {768.0, 1024.0}}
Table, 0x600000d98b60, {{10.0, 30.0}, {320.0, 400.0}}
Cell, 0x600000d98c30, {{10.0, 30.0}, {320.0, 44.0}}
StaticText, 0x600000d98d00, {{25.0, 30.0}, {290.0, 43.5}}, identifier: 'world', label: 'hello'
Other, 0x600000d98dd0, {{25.0, 73.5}, {305.0, 0.5}}
Perhaps it is more of this UITableViewCell odd/unexplained behavior?
The other strangeness that leads me to this is when a UIScrollView
containing a UILabel
is added to a UITableViewCell
, the UIScrollView
does not appear in the hierarchy. So this:
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath] ;
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UIScrollView *sv = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
UILabel *lb = [[UILabel alloc] initWithFrame:CGRectMake(0,0, 5,5)];
[lb setText:@"hello world"];
[sv addSubview:lb];
[[cell contentView] addSubview:sv];
return cell;
}
yields this:
Element subtree:
→Application, 0x6000014e75a0, pid: 20372, label: 'TestApp'
Window (Main), 0x6000014e7190, {{0.0, 0.0}, {768.0, 1024.0}}
Other, 0x6000014e6ff0, {{0.0, 0.0}, {768.0, 1024.0}}
Table, 0x6000014e6f20, {{10.0, 30.0}, {320.0, 400.0}}
Cell, 0x6000014e6e50, {{10.0, 30.0}, {320.0, 44.0}}
StaticText, 0x6000014e6d80, {{10.0, 30.0}, {5.0, 5.0}}, label: 'hello world'
Other, 0x6000014e6cb0, {{25.0, 73.5}, {305.0, 0.5}}
Whereas this (no table or cell involved):
- (void)viewDidLoad {
[super viewDidLoad];
UIScrollView *sv = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
UILabel *lb = [[UILabel alloc] initWithFrame:CGRectMake(0,0, 5,5)];
[lb setText:@"hello world"];
[sv addSubview:lb];
[self.view addSubview:sv];
}
seems to work just fine:
Element subtree:
→Application, 0x600000278750, pid: 20442, label: 'TestApp'
Window (Main), 0x6000002788f0, {{0.0, 0.0}, {768.0, 1024.0}}
Other, 0x600000278820, {{0.0, 0.0}, {768.0, 1024.0}}
ScrollView, 0x6000002789c0, {{0.0, 0.0}, {10.0, 10.0}}
StaticText, 0x600000278a90, {{0.0, 0.0}, {5.0, 5.0}}, label: 'hello world'
My thoughts are that this is all somehow related to the way isAccessibilityElement
, accessibilityTraits
and whether or not a view is a container determine what gets exposed but the inconsistency is bewildering and I'm hoping someone else knows the secret formula.
This other element is the separation line between cells. Since these lines don't affect other elements, they should not bother you.
When you make some element accessible, its descendants don't appear in UI tests elements tree.