I'm trying to get the position of a UI element from the Notification Center. I can do so when I get a list of coordinates (an x and y posn
) and then reference each one individually. However when I try to do it directly, I get a type coercion error.
System Events got an error: Can’t make item 1 of position of group 1 of UI element 1 of scroll area 1 of window "Notification Center" of process "Notification Center" into type specifier.
.
Here's the example code:
activate application "NotificationCenter"
tell application "System Events"
tell process "Notification Center"
-- works
set xyPositions to position of group 1 of UI element 1 of scroll area 1 of window "Notification Center"
set xPos to item 1 of xyPositions
-- fails with error
set xPos to item 1 of position of group 1 of UI element 1 of scroll area 1 of window "Notification Center"
end tell
end tell
I'd like to know what's going on, since the two methods seem equivalent.
CodePudding user response:
They look equivalent but they are not:
set xyPositions to position of group 1 of UI element 1 of scroll area 1 of window "Notification Center"
is really shorthand for:
set xyPositions to get position of group 1 of UI element 1 of scroll area 1 of window "Notification Center"
When AppleScript sees an object specifier, it determines if that specifier points to a property or element(s) of a local AppleScript value (string, list, record, etc) or a remote application (in this case, System Events).
If the specifier points to an application, and the specifier isn’t already a parameter to an application command (move
, duplicate
, delete
, etc), AppleScript automatically performs a get
command (aka “implicit get”) to resolve that object specifier. In your example, this returns the value of the position
property, which is an AppleScript list. The second line then works as you’d expect:
set xPos to item 1 of xyPositions
as AppleScript extracts the first item of that list.
When you combine the two lines into one, you are telling the application to get item 1 of the position property:
set xPos to [get] item 1 of position of group 1 of UI element 1 of scroll area 1 of window "Notification Center"
However the application doesn’t know how to do this—it can only access objects within its object model. It doesn’t know how to manipulate the contents of primitive strings, lists, records, etc; only AppleScript can do that. Thus the application command fails.
If you wish to combine the two lines into one, you must use an explicit get
command to resolve the application specifier before manipulating its result:
set xPos to item 1 of (get position of group 1 of UI element 1 of scroll area 1 of window "Notification Center")
Yes, it’s confusing. But that’s AppleScript for you: it tries to be “simple” and “helpful” to make it easy for non-experts to use, but really all it does is obfuscate what’s actually going on underneath that superficially friendly syntax. When it works, it’s like arcane magic. When it confounds, it’s like arcane magic. So it goes.