诸如按钮之类的“叶子”UI 元素将位于可能复杂的 UI 元素层次结构的底部,在 iTunes 中尤其如此。
为了让您了解一下,这里有一个免费应用程序的 App Store 页面上按钮的示例对象说明符Get
(假设您已经确保该页面处于活动状态):
Application("System Events")
.applicationProcesses.byName("iTunes")
.windows.byName("iTunes")
.splitterGroups.at(0)
.scrollAreas.at(0)
.uiElements.at(0)
.groups.at(3)
.buttons.at(0)
问题是这个对象说明符因页面而异,因此理想情况下,您只需将过滤器应用于所有UI 元素(通过窗口的entireContents
属性)以检索感兴趣的按钮:
// Get an array of all UI elements in iTunes window.
uiElems = Application("System Events").applicationProcesses['iTunes']
.windows[0].entireContents()
// Find all buttons whose description contains 'Get'.
btns = uiElems.filter(function(el) {
try {
return el.role() == 'AXButton'
&&
el.description().match(/\bGet\b/)
} catch (e) {}
})
// Click on the 1st button found.
btns[0].click()
这里有一个问题:在我相当新的机器上,这大约需要 20 秒(!)。
我会想象一个.whose
-style 过滤器会更快,但我无法让它在这种情况下工作,因为必须捕获异常 - 如上所述 - 但.whose
似乎不支持嵌入式异常处理程序。
如果您愿意假设可以在其子树中找到按钮的层次结构中的较低级别,则可以大大加快速度:
// Get the group UI elements in one of which the 'Get' button is located.
grps = Application("System Events").applicationProcesses['iTunes'].
windows[0].splitterGroups[0].scrollAreas[0].uiElements[0].groups
// Loop over groups
count = grps.length
for (i = 0; i < count; ++i) {
// In the group at hand, find all buttons whose description contains 'Get'.
btns = grps[i].entireContents().filter(function(el) {
try {
return el.role() == 'AXButton'
&&
el.description().match(/\bGet\b/)
} catch (e) {}
})
// Exit loop, if a 'Get' button was found.
if (btns.length > 0) break
}
if (btns.length == 0) {
console.log('ERROR: No "Get" button found.')
} else {
// Click on the 1st button found.
btns[0].click()
}
这将在不到 1 秒的时间内运行。在我的机器上。
不幸的是,UI 自动化(GUI 脚本)是一项棘手的工作。
对于交互式探索,Xcode 附带了Accessibility Inspector开发人员工具,但使用它并非易事,尤其是在将发现转换为代码时。