ボタンなどの「リーフ」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
スタイルのフィルターの方が高速だと思いますが、上記のように例外をキャッチする必要があるため、この例ではそれを機能させることができませんでしたが、.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開発者ツールがありますが、特に調査結果をコードに変換する場合は、それを使用するのは簡単ではありません。