-
Notifications
You must be signed in to change notification settings - Fork 5
Igor Usage Tips
There are two directions to read an Igor query: from left to right, and from right to left. If a query is difficult to understand when you read it in one direction, try reading it in the other.
Consider this example:
UIScrollView > * > [accessibilityLabel == 'cows']
We can read this from left to right as a procedure for finding the views we're interested in:
- Find every
UIScrollView
- Then find all of the children of those views.
- Then find the children of those views
whose
accessibilityLabel
is 'cows'.
We can also read the query from right to left, as a description of the views we're interested in:
Every view whose
accessibilityLabel
is 'cows',
... and is a child of any view
... that is a child of a `UIScrollView`.
We can shorten this to:
Every view whose
accessibilityLabel
is 'cows',
... and is a grandchild of a UIScrollView.
Sometimes you want to find a view based on properties of its descendants.
Suppose your app displays a table,
and one of the cells in the table
contains a view identified (by its accessibilityIdentifier
property)
as 'Barney'.
And suppose you want to find the table view cell that contains the Barney view. You can do that by using a subject marker:
$UITableViewCell #Barney
This query tells Igor to find every place in the view hierarchy
where a UITableViewCell
has a descendant #Barney
.
The dollar sign tells Igor to select the table cells.
Subject markers change the way you read a query. You can read this query from left to right like this:
A
UITableViewCell
... that contains a descendant whose `accessibilityIdentifier` is 'Barney'.
Sometimes you want to find a view based on its relationship to some other view that has a common ancestor.
Suppose your app displays a table and you've already tapped the Edit button to enter edit mode:
Now suppose you want to delete the row labeled '2'. To do this, you have to find the delete button for that row. Here is part of the view hierarchy:
We know some facts about the delete button:
- Its class is
UITableViewCellEditControl
- Its text is 'Delete '
We can use either of these facts to locate the button. But notice that there are several other buttons with the same features. The facts we know about the delete button do not uniquely identify the one we want to tap.
But we do know that the delete button we want to tap is in the same row
as the UILabel
with text '2'.
With this information,
we can construct a query that says
"select the delete button that is in the same table cell as the row labeled '2'."
To construct such a query, we first need to identify three pieces:
-
The target view—the view that we ultimately want to select. In our example, the target view is a view whose class is
UITableViewCellEditControl
. -
A reference view—some view that we know how to find, and that bears a meaningful relationship to the target view. In our example, the reference view is a
UILabel
with text '2'. -
A common ancestor—a view that contains both the target view and the reference view. In our example, the nearest common ancestor is the
UITableViewCell
that contains theUILabel
whose text is '2'.
Here are the steps to build up the query from these pieces:
-
Write a query that selects the reference view, like this:
UILabel[text == '2']
-
Prepend patterns to show the reference view's relationship to the common ancestor:
UITableViewCell UILabel[text == '2']
-
Wrap the query in parentheses to form a branch pattern:
(UITableViewCell UILabel[text == '2'])
This branch pattern all by itself is equivalent to:
$UITableViewCell UILabel[text == '2']
. It selects the table view cell that is an ancestor of the label with text '2'. That is: It selects our desired common ancestor. -
Append the relationship between the common ancestor and the target view:
(UITableViewCell UILabel[text == '2']) UITableViewCellEditControl
And there you have it: Cousins! A query that selects a view based on its relationship to some other view within a common ancestor.