I’ve been playing around with a little script in AppleScript to look up UI elements in a program by their name. This is basically the function:
on getElementByClassAndName(targetName, targetElements)
repeat with uiElem in targetElements as list
set elName to (name of uiElem)
if (elName is targetName) then
return uiElem
exit repeat
end if
end repeat
return false
end getElementByClassAndName
And here is an example of its use with TextEdit:
tell application "System Events"
tell process "TextEdit"
set win to front window
set myElement to my getElementByClassAndName("Minimize", entire contents)
log (myElement)
end tell
end tell
The logic is simple: go over the UI elements in a window, check if the name is equal to a provided string. The problem is that it can take 10-20 seconds depending on the application. If you add a counter, you can see that even if it is not checking that many elements (say, 100), it is ridiculously slow.
The part that is slow is clearly set elName to (name of uiElem)
. If you remove this and replace it with, say, set elName to false
, the script executes almost instantly (but of course does not find the element).
It is amazing to me that looking up the name
property is so slow. By comparison, if you instead just add a log(uiElem)
in there (without looking up the specific name
property), it executes instantly as well. So log
is somehow able to get the name
info (and lots of other info) much faster than accessing the actual name
property directly. Madness.
Is there a way to possibly speed this up, to more directly reference properties of UI elements? It feels bizarre that I can log(entire contents)
and other gigantic lists instantly but cannot iterate over the elements in them without increasing the runtime by a factor of 100 or more.
I have tried more unwieldy ways to reference the name
, and they seem to take the same amount of time. Is there a faster way to do it? (Why is it so slow?)