visionOS で iPad アプリ相当を動かす #11 - #51
Merged
Merged
Conversation
SUPPORTED_PLATFORMS gains xros/xrsimulator on both targets, with XROS_DEPLOYMENT_TARGET 26.0, TARGETED_DEVICE_FAMILY "2,7" and the visionOS spellings of UISupportsDocumentBrowser. Nothing in the layout is conditional: the scene is regular width, so the same three-pane NavigationSplitView fills the window, and both packages had already declared .visionOS(.v26). What the platform actually costs is the #ifs, in both directions. A guard written `#if os(iOS)` compiles clean on visionOS and simply stops applying, which had silently dropped the launch scene (DocumentGroupLaunchScene is unavailable on macOS only), the numeric keyboard and the 44pt touch targets; those are `#if !os(macOS)` now. And some API is genuinely gone: ToolbarSpacer, the Liquid Glass grouping separator, which is why the canvas toolbar becomes a CanvasToolbar: ToolbarContent — somewhere for the #if to live that isn't the call site. CI builds visionOS for exactly this reason; nothing else catches a guard that quietly does nothing. pointerHover() stays iOS-only, and says why. hoverEffect on a palette entry segfaults inside SwiftUI's own update of PaletteEntryButton.body before a window is ever shown, with .automatic as well as .highlight, so it is the modifier rather than the effect. Buttons get the system's hover treatment there anyway. Verified by opening a real document in the visionOS 27 simulator: palette, workspace, canvas, playback row and the document title all render as they do on iPadOS, and drag & drop and the four value-slot popovers behave. The app icon is the one thing still missing. visionOS wants a circular layered icon and Icon Composer only writes squares (plus watchOS circles), so AppIcon.icon produces nothing for it and the system placeholder is what shows on the Home View. #11
`ideal` carries more weight than it looks. macOS and iPadOS 26 both let the split view's divider be dragged, so there it is only where the column opens; visionOS has no draggable divider, so there it is the width, permanently, and the detail column absorbs every extra point the window has. Measured on a 1280pt visionOS window: 360 for the workspace against ~690 for the canvas, which is 270 past the canvas's own ideal. At 360 a nested Japanese program wraps, and not only where the design had accepted it. 「くりかえす 10 かい」 broke か/い at the *top* level, no nesting involved, and 「はこにかける」 split in the middle three levels down. 440 fits every row of that program on one line at three levels — each level of nesting costs 18pt — and still leaves the canvas ~600pt. max goes to 560 because ideal == max would leave the two platforms that can drag able to drag only narrower. Checked against the same three-deep document on visionOS 27 and on a 1280×800 Mac window. Judge any change to it on a nested *Japanese* program: English fits where 「はこにかける」 does not, and the top-level wrap is invisible in a flat one. #11
Icon Composer writes squares (plus watchOS circles) and nothing else, so AppIcon.icon left visionOS with the system placeholder. The circular layered icon comes from a second source instead: an AppIcon.solidimagestack of three .solidimagestacklayers — Front, Middle, Back at 1024×1024 on the vision idiom — carrying the same artwork as the Icon Composer icon, so the tortoise reads the same in the Home View as it does in the Dock and on a Home Screen. Both are named AppIcon and neither shadows the other: ASSETCATALOG_COMPILER_APPICON_NAME is one value for every platform and actool routes by idiom. Verified in the built products, not in Xcode — the visionOS Assets.car holds a SolidImageStack and no IconImageStack, the iOS one the reverse, and the Mac still ships AppIcon.icns. Checked on the visionOS 27 Home View too, which is the only place the layers and the circular mask are actually applied. #11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#11 の「visionOS で iPad アプリ相当が動く」まで。3 コミットに分けてあります。
1.
Build and run on visionOSSUPPORTED_PLATFORMSにxros xrsimulator、XROS_DEPLOYMENT_TARGET 26.0、TARGETED_DEVICE_FAMILY "2,7"、UISupportsDocumentBrowserの visionOS 綴り(両ターゲット)。レイアウトは一切分岐していません — visionOS のシーンは regular width なので、同じ 3 ペインのNavigationSplitViewがそのまま成立します。両パッケージは元から.visionOS(.v26)宣言済みでした。実際に手間だったのは
#ifで、両方向に問題がありました。#if os(iOS)は visionOS で静かに効かなくなる — コンパイルは通るので気付けません。これで起動画面(DocumentGroupLaunchSceneが unavailable なのは macOS だけ)・数字キーボード・44pt のタップ領域が丸ごと落ちていました。#if !os(macOS)に書き換えToolbarSpacer(Liquid Glass のグルーピング区切り)。呼び出し側に#ifを置かずに済ませるため、キャンバスのツールバーをCanvasToolbar: ToolbarContentに切り出しましたCI の app-build マトリクスに visionOS を追加したのはこのためです。「効かなくなった
#if」を検出する手段は他にありません。pointerHover()は iOS 限定のままにしてあります。visionOS では視線フィードバックこそ本来の用途に見えますが、hoverEffectをパレットに付けるとウィンドウが出る前に落ちます(PaletteEntryButton.bodyを更新中の SwiftUI 内部のswift_releaseで segfault)。.automaticでも.highlightでも同じなので、効果の種類ではなくモディファイア自体です。理由はコードコメントに残しました。visionOS はボタンに標準のホバー処理を付けるので、見た目の実害はありません。2.
Open the workspace column at 440ptこれは visionOS 固有ではなく、3 プラットフォーム共通の変更なので分けました。
idealの重みがプラットフォームで違います。macOS と iPadOS 26 はディバイダをドラッグできるのでidealは「開いたときの幅」ですが、visionOS はドラッグできないのでidealがその列の幅そのものになり、余った幅は全部 detail が吸います。1280pt のウィンドウで実測:ideal)360pt では 3 段ネストの日本語プログラムがラベルを折り返します。しかも深いところだけではなく、最上段の「くりかえす 10 かい」が か/い で割れていました(ネスト 0 段)。440 なら 3 段目の「はこにかける」まで全部 1 行に収まり、キャンバスも自分の ideal 420 を超えたままです。
maxを 440→560 にしたのは、ideal == maxだとドラッグできる 2 つのプラットフォームが狭める方向にしか動かせなくなるためです。3.
Give visionOS an app iconIcon Composer は squares(と watchOS の circles)しか書き出せないので、
AppIcon.iconからは visionOS 用が 1 枚も出ず、ホーム画面はシステムのプレースホルダのままでした。Assets.xcassets/AppIcon.solidimagestack(Front / Middle / Back の 3 レイヤー、visionidiom の 1024×1024)を追加。同名の 2 ソースは共存します。
ASSETCATALOG_COMPILER_APPICON_NAMEは全プラットフォーム共通でAppIconのまま、actool が idiom で振り分けます。ビルド生成物で確認済み:SolidImageStack | AppIcon+ 3 レンディション、IconImageStackは無しIconImageStack/IconGroup AppIcon/Tortoise、SolidImageStackは無しAppIcon.icns確認したこと
swift test119 tests green、swift format lint --strictclean未確認
openurlで開けなかったため。同じidealを読むので結果は同じはずですが、3 段ネストの日本語プログラムで見てもらえると確実です(英語だと収まってしまい、最上段の折り返しはフラットなプログラムでは出ません)相談
**
Fixes #11を付けていません。**issue のチェックリスト 4 項目はすべて埋まりましたが、出荷側が残っているためです。site/index.htmlとappstore/metadata/*/description.txtの「iPad and Mac」— この PR では意図的に触っていません。あれは「ダウンロードできるもの」の約束なので、出荷が決まってから直すのが正しいと判断しました。README だけは「このリポジトリから何がビルドできるか」なので visionOS 26+ を追加してありますこれらを別 issue に切って #11 を閉じるか、#11 に残すか、指示ください。閉じる方針なら最後のコミットに
Fixes #11を付け替えます。