ÿÿ既存ã®ã‚³ãƒ¼ãƒ‰ãƒ™ãƒ¼ã‚¹ã‹ã‚‰visionOSå‘ã‘ã®ä¸€æµä½“験をCraftã§ã©ã®ã‚ˆã†ã«å®Ÿç¾ã—ãŸã‹

→ Craft Plus and Family ãŒ40%オフ

既存ã®ã‚³ãƒ¼ãƒ‰ãƒ™ãƒ¼ã‚¹ã‹ã‚‰visionOSå‘ã‘ã®ä¸€æµä½“験をCraftã§ã©ã®ã‚ˆã†ã«å®Ÿç¾ã—ãŸã‹

æ–°ã—ã„プラットフォームã¸ã®å‚å…¥ã¯ã€é–‹ç™ºè€…ã®äººç”Ÿã«ãŠã„ã¦æ•°ãˆã‚‹ã»ã©ã—ã‹ãªã„特別ãªå‡ºæ¥äº‹ã§ã™ã€‚ãã‚Œã¯æœ¬å½“ã«æ–°ã—ã„領域ã«è¸ã¿è¾¼ã‚€ã€ç¨€ã§åˆºæ¿€çš„ãªçž¬é–“ã§ã™ã€‚ç´ æ—©ãå‹•ã‘ã°ã€ã‹ã¤ã¦ã®æŽ¢æ¤œå®¶ã®ã‚ˆã†ãªæ°—æŒã¡ã«ãªã‚Œã¾ã™ã€‚ã™ã¹ã¦ãŒæ–°é®®ã§ã€ç¢ºç«‹ã•れãŸãƒ‘ターンãŒãªã„ã‹ã‚‰ã“ãã€å®Ÿé¨“ã®ä½™åœ°ãŒåºƒãŒã£ã¦ã„ã¾ã™ã€‚

執筆者
Craft著者: Kristof Gruber
Kristof Gruber
公開日
2024年5月15日
Craftã¥ãり
既存ã®ã‚³ãƒ¼ãƒ‰ãƒ™ãƒ¼ã‚¹ã‹ã‚‰visionOSå‘ã‘ã®ä¸€æµä½“験をCraftã§ã©ã®ã‚ˆã†ã«å®Ÿç¾ã—ãŸã‹

ç§ãŸã¡Craftã«ã¯ã™ã§ã«ã“ã®æ©Ÿä¼šãŒä¸€åº¦ã‚りã¾ã—ãŸã€‚Mac Catalystã¨ã„ã†ç´ æ™´ã‚‰ã—ã„æŠ€è¡“ã‚’ä½¿ã„å§‹ã‚ãŸã¨ãã§ã™ã€‚ã“れã«ã‚ˆã‚Šã€iOSアプリをMacã«å±•é–‹ã™ã‚‹ã“ã¨ãŒã§ãã¾ã—ãŸã€‚ãれ以æ¥ã€iOSã€iPadOSã€macOSã¨ã„ã£ãŸç§ãŸã¡ãŒã‚µãƒãƒ¼ãƒˆã™ã‚‹ã™ã¹ã¦ã®ãƒ—ラットフォームã§ã‚¢ãƒ—リを構築ã™ã‚‹ãŸã‚ã«å…±é€šã®ã‚³ãƒ¼ãƒ‰ãƒ™ãƒ¼ã‚¹ã‚’使用ã—ã¦ã„ã¾ã™ã€‚visionOSã®ç™»å ´ã«ã‚ˆã‚Šã€ç§ãŸã¡ã¯ã“ã®å …固ãªåŸºç›¤ã®ä¸Šã«æ§‹ç¯‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã—ãŸã€‚

ã“ã®è¨˜äº‹ã§ã¯ã€Craftã‚’Vision Proã«ç§»æ¤ã—ãŸãƒ—ロセスを紹介ã—ã€ã„ãã¤ã‹ã®èˆˆå‘³æ·±ã„å­¦ã³ã‚’ãŠä¼ãˆã—ã¾ã™ã€‚

  • ä¾å­˜é–¢ä¿‚ã‚’æ›´æ–°ã™ã‚‹ï¼š 使用ã—ã¦ã„るライブラリãŒvisionOSをサãƒãƒ¼ãƒˆã™ã‚‹ã‚ˆã†æ›´æ–°ã•れã¦ã„ã‚‹ã‹ç¢ºèªã™ã‚‹
  • éžæŽ¨å¥¨APIã‚’é¿ã‘る: Appleã¯æ•°å¹´å‰ã«éžæŽ¨å¥¨ã¨ãªã£ã¦ã„ãŸå¤ã„API呼ã³å‡ºã—ã‚’ã™ã¹ã¦å‰Šé™¤ã—ãŸ
  • UIScreenã«é ¼ã‚‰ãªã„: ã“れらã®å¤ã„制約ã¯ã‚‚ã†å­˜åœ¨ã—ãªã„ホãƒãƒ¼ã‚¨ãƒ•ェクトを使用ã™ã‚‹ï¼šãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ç›®ãŒå‘ã„ãŸã¨ãã«ã‚·ã‚¹ãƒ†ãƒ æä¾›ã®ãƒã‚¤ãƒ©ã‚¤ãƒˆã‚’サãƒãƒ¼ãƒˆã™ã‚‹ã‚ˆã†ã‚«ã‚¹ã‚¿ãƒ ãƒ“ューを改善ã™ã‚‹
  • ダークモードã¨ãƒ©ã‚¤ãƒˆãƒ¢ãƒ¼ãƒ‰ã®ãªã„アプリを準備ã™ã‚‹ï¼š アプリã¯ã‚·ã‚¹ãƒ†ãƒ æä¾›ã®ã‚¬ãƒ©ã‚¹ãƒžãƒ†ãƒªã‚¢ãƒ«ã«é©å¿œã™ã‚‹å¿…è¦ãŒã‚りã€ãれã¯ä¸€ã¤ã®çŠ¶æ…‹ã—ã‹æŒãŸãªã„
  • UIã«ã‚¹ãƒšãƒ¼ã‚¹ã‚’与ãˆã‚‹ï¼š visionOSã§ã¯UIè¦ç´ ãŒã‚ˆã‚Šå¤§ããã€è¦ç´ é–“ã®ã‚¹ãƒšãƒ¼ã‚¹ã‚‚広ã„
  • 3ã¤ã®å…¥åŠ›æ–¹æ³•ã™ã¹ã¦ã‚’サãƒãƒ¼ãƒˆã™ã‚‹ï¼š ユーザーã¯ã‚¢ã‚¤ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã€ãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã‚¿ãƒƒãƒã€ã¾ãŸã¯ãƒˆãƒ©ãƒƒã‚¯ãƒ‘ッドを接続ã—ãŸãƒã‚¤ãƒ³ã‚¿ãƒ¼ã‚’使用ã§ãã‚‹
  • 3Dã§å·®åˆ¥åŒ–ã™ã‚‹ï¼š SwiftUIを使ã£ã¦ãƒ¬ã‚¤ãƒ¤ãƒ¼ã‚’3次元空間ã«ç§»å‹•ã•ã›ã‚‹
  • アクセシビリティã«é…æ…®ã™ã‚‹ï¼š 常ã«ã‚¢ã‚¯ã‚»ã‚·ãƒ“リティオプションを有効ã«ã—ã¦ã‚¢ãƒ—リをテストã™ã‚‹

ロードマップ

CraftãŒvisionOSã®App Storeã«é©ã—ãŸå€™è£œã ã¨åˆ¤æ–­ã—ãŸå¾Œã€ã™ãã«ãã®ãƒ—ラットフォームå‘ã‘ã®ã‚¢ãƒ—リ構築ã®å®Ÿé¨“ã‚’å§‹ã‚ã¾ã—ãŸã€‚ã‚‚ã¡ã‚ã‚“ã€æœ€åˆã¯å¤±æ•—ã®é€£ç¶šã§ã—ãŸã€‚何もã™ãã«ã¯å‹•ãã¾ã›ã‚“ã§ã—ãŸã€‚å•題を調査ã—ã€ã‚³ãƒ¼ãƒ‰ãƒ™ãƒ¼ã‚¹å…¨ä½“ã‚’ç´ æ—©ãå復ã—ã¦ã€å‹•作ã—ãªã„コードをã™ã¹ã¦å‰Šé™¤ã—ã¾ã—ãŸã€‚プラットフォーム上ã§CraftãŒã©ã®ã‚ˆã†ã«è¦‹ãˆã‚‹ã‹ã€ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’作æˆã™ã‚‹ã®ãŒã©ã‚Œã»ã©é›£ã—ã„ã‹ã‚’ç´ æ—©ã確èªã—ãŸã‹ã£ãŸã ã‘ã§ã™ã€‚動作ã•ã›ã‚‹ãŸã‚ã«ã„ãã¤ã‹ã®ä¾å­˜é–¢ä¿‚を削除ã—ã€ä¸€éƒ¨ã®é–¢æ•°ã‚’コメントアウトã™ã‚‹å¿…è¦ãŒã‚りã¾ã—ãŸãŒã€æ•°æ™‚é–“ã®ä½œæ¥­ã§æ¸ˆã¿ã€å¹¸ã„ãªã“ã¨ã«é‡è¦ãªã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã¯å£Šã‚Œã¦ã„ã¾ã›ã‚“ã§ã—ãŸã€‚XcodeãŒæ–°ã—ã„OSã«å¯¾ã—ã¦Craftã‚’åˆã‚ã¦ãƒ“ルドã—ã€ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ãƒ¼ã§å‹•ãå§‹ã‚ã‚‹ã®ã‚’見るã“ã¨ãŒã§ãã¾ã—ãŸã€‚

image

開始当åˆã®çŠ¶æ…‹ã€‚ãƒ¡ã‚¤ã‚¯ã‚¢ãƒƒãƒ—å‰ã§ã‚‚ã€ã™ã§ã«ãƒã‚¤ãƒ†ã‚£ãƒ–ã§å‹•作ã—ã¦ã„ã‚‹

ã‚‚ã¡ã‚ã‚“ã€å°‘ã—è’削りãªçŠ¶æ…‹ã§ã—ãŸã€‚アプリã®ã»ã¨ã‚“ã©ã¯3D空間ã«åŸ‹ã‚è¾¼ã¾ã‚ŒãŸiPadアプリã®ã‚ˆã†ã«è¦‹ãˆã€ä¸€éƒ¨ã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェースカラーã€ãƒœã‚¿ãƒ³ã®å½¢çжã€å‰Šé™¤ã•れãŸã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã«ä¾å­˜ã™ã‚‹ã‚‚ã®ã¯å£Šã‚Œã¦ã„ã¾ã—ãŸãŒã€æœ¬ç‰©ã§ã‚ã‚‹ã“ã¨ã«å¤‰ã‚りã‚りã¾ã›ã‚“ã€‚åŒæœŸã‚„ドキュメント編集ã¨ã„ã£ãŸé‡è¦ãªéƒ¨åˆ†ã¯ã™ã§ã«æ©Ÿèƒ½ã—ã¦ã„ã¾ã—ãŸã€‚ã“れãŒãƒ—ロジェクトã«ã‚´ãƒ¼ã‚µã‚¤ãƒ³ã‚’出ã—ãŸæ™‚点ã§ã™ã€‚

ç§ãŸã¡ã¯Vision Proãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ホビープロジェクトã¨ã—ã¦æ‰±ã„ã¾ã—ãŸã€‚メインアプリã®é–‹ç™ºã«ä½™è£•ãŒç”Ÿã¾ã‚ŒãŸã¨ãã«å–り組ã¿ã¾ã—ãŸã€‚リリースã«å‘ã‘ã¦ã„ãã¤ã‹ã®é‡è¦ãªã‚¹ãƒ†ãƒƒãƒ—を設定ã—ã¾ã—ãŸï¼š

  1. プロジェクト作業 æ–°ã—ã„プラットフォームを追加ã—ã€ãƒ©ã‚¤ãƒ–ラリを更新ã—ã€ä¸è¦ãªéƒ¨åˆ†ã‚’削除ã—ã€æ–°ã—ã„OSã§ãƒ—ロジェクトをビルドã§ãるよã†ã«ã™ã‚‹
  2. 調整 visionOSå‘ã‘ã«ãƒ—ロジェクトを調整ã™ã‚‹ã€‚欠ã‘ã¦ã„るクラスã€ç•°ãªã‚‹æ©Ÿèƒ½ã€æ–°ã—ã„æ©Ÿèƒ½ã«å¯¾å‡¦ã™ã‚‹
  3. 美ã—ãã™ã‚‹ æ–°ã—ã„デザイン言語ã«åˆã‚ã›ã¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェースを改善ã™ã‚‹

ã“れらã®ã‚¹ãƒ†ãƒƒãƒ—を一ã¤ãšã¤è¦‹ã¦ã„ãã¾ã—ょã†ã€‚

プロジェクト作業

最åˆã®ç°¡å˜ãªãƒ†ã‚¹ãƒˆã®å¾Œã€ãƒ¡ã‚¤ãƒ³ãƒ–ランãƒã‹ã‚‰æ´¾ç”Ÿã—ãŸæ–°ã—ã„ブランãƒã§æœ€åˆã‹ã‚‰å§‹ã‚ç›´ã—ã¾ã—ãŸã€‚最åˆã®ã‚¹ãƒ†ãƒƒãƒ—ã¯ã€Xcodeã®ã‚µãƒãƒ¼ãƒˆã•れã¦ã„るプラットフォームリストã«Apple Visionデスティãƒãƒ¼ã‚·ãƒ§ãƒ³ã‚’追加ã™ã‚‹ã“ã¨ã§ã—ãŸã€‚ã“れã«ã‚ˆã‚Šä¾å­˜é–¢ä¿‚ã«å¤šãã®å•題ãŒç”Ÿã˜ãŸãŸã‚ã€æœ€åˆã®ã‚¿ã‚¹ã‚¯ã¯ã™ã¹ã¦ã®ãƒ©ã‚¤ãƒ–ラリを確èªã—ã¦å•題を修正ã™ã‚‹ã“ã¨ã§ã—ãŸã€‚

ä¾å­˜é–¢ä¿‚ã®ä¸­ã«ã¯ã™ã§ã«visionOSをサãƒãƒ¼ãƒˆã™ã‚‹ã‚ˆã†æ›´æ–°ã•れã¦ã„ãŸã‚‚ã®ã‚‚ã‚りã€ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã‚’上ã’ã¦æ›´æ–°ã—ã€æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒä»¥å‰ã¨åŒæ§˜ã«æ©Ÿèƒ½ã™ã‚‹ã‹ã‚’ç°¡å˜ã«ç¢ºèªã™ã‚‹ã ã‘ã§æ¸ˆã¿ã¾ã—ãŸã€‚

残念ãªãŒã‚‰ã€ä½¿ç”¨ã—ã¦ã„るライブラリã®ä¸­ã«ã¯æ›´æ–°ã•れã¦ã„ãªã„ã‚‚ã®ã‚‚ã‚りã€è¿‘ã„å°†æ¥ã«å¿…è¦ãªå¤‰æ›´ã‚’サãƒãƒ¼ãƒˆã™ã‚‹è¦‹è¾¼ã¿ã‚‚ã‚りã¾ã›ã‚“ã§ã—ãŸã€‚ãれらã«ä¾å­˜ã—ã™ãŽã¦ã„ãŸãŸã‚削除もã§ããšã€Craftã®GitHubアカウントã§ãƒ•ォークã—ã¾ã—ãŸã€‚æ›´æ–°ã¯ç°¡å˜ã§ã—ãŸã€‚ã»ã¨ã‚“ã©ã®å ´åˆã€å•題ã¯å„プラットフォーム(iOSã€macOSã€tvOSã€watchOS)ã”ã¨ã«æ˜Žç¤ºçš„ãªå‹•作ãŒå®šç¾©ã•れã¦ãŠã‚Šã€ãれ以外ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå®Ÿè£…ãŒæä¾›ã•れã¦ã„ãªã„ã“ã¨ã§ã—ãŸã€‚ã¤ã¾ã‚Šã€visionOSã«ã¯å®Ÿè£…ãŒå…¨ããªã‹ã£ãŸã®ã§ã™ã€‚

visionOSã«å­˜åœ¨ã—ãªã„APIコールやオブジェクトã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ãƒ©ã‚¤ãƒ–ラリもã„ãã¤ã‹ã‚りã¾ã—ãŸï¼ˆä¾‹ãˆã°UIScreenã«ã¤ã„ã¦ã¯å¾Œè¿°ã—ã¾ã™ï¼‰ã€‚ã“れらã¯ç°¡å˜ã«å›žé¿ã§ãã¾ã—ãŸã€‚

残念ãªãŒã‚‰ã€è‡ªåˆ†ãŸã¡ã§ã¯ä¿®æ­£ã§ããªã„(例ãˆã°ã‚¯ãƒ­ãƒ¼ã‚ºãƒ‰ã‚½ãƒ¼ã‚¹ã®ãŸã‚)ãŒå›žé¿ã§ãã‚‹ä¾å­˜é–¢ä¿‚ã‚‚ã‚りã€ãƒ—ロジェクトã‹ã‚‰å‰Šé™¤ã—ã¾ã—ãŸã€‚Googleã¯æ®‹å¿µãªãŒã‚‰Appleã®æ€¥é€Ÿãªãƒ—ラットフォーム開発ã«ã¤ã„ã¦ã„ãã®ãŒæ—©ããªã„ã“ã¨ã§çŸ¥ã‚‰ã‚Œã¦ãŠã‚Šã€ãã®ãŸã‚「Googleã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã€ãƒœã‚¿ãƒ³ã¯å‰Šé™¤ã—ãªã‘れã°ãªã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚ライブラリを削除ã—ã¦ã‚‚ä»–ã®ãƒ—ラットフォームã«ã¯å½±éŸ¿ã™ã¹ãã§ã¯ã‚りã¾ã›ã‚“。幸ã„ã€Xcodeプロジェクトã§ã¯ãれを設定ã§ãã¾ã™ï¼š

image

ä»–æ–¹ã§ã¯ã€å¯¾å¿œã™ã‚‹éƒ¨åˆ†ã®å‘¼ã³å‡ºã—を無効化ã™ã‚‹ãŸã‚ã«#if os(visionOS)マクロを追加ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ãŒã€ãれã ã‘ã§ã™ã€‚

ã¾ãŸã€Shortcutsサãƒãƒ¼ãƒˆãªã©ã®App Extensionã®ã»ã¨ã‚“ã©ã‚‚削除ã—ã¾ã—ãŸï¼ˆå°‘ãªãã¨ã‚‚今ã®ã¨ã“ã‚)。ã“れらã¯ã„ãã¤ã‹ã®ãƒ“ルドエラーを引ãèµ·ã“ã—ã€ã¾ãšã‚¢ãƒ—リ本体ã«é›†ä¸­ã—ãŸã‹ã£ãŸãŸã‚ã§ã™ã€‚後ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯æœ€çµ‚çš„ã«ã“れらを追加ã—ç›´ã™äºˆå®šã§ã™ã€‚

æ–°ã—ã„環境ã¸ã®èª¿æ•´

å‰ã®ãƒ•ェーズを経ã¦ã€ãƒ—ロジェクトã¯ã¾ã ã‚³ãƒ³ãƒ‘イルã§ãã¾ã›ã‚“ã§ã—ãŸãŒã€å°‘ãªãã¨ã‚‚ã™ã¹ã¦ã®ã‚¨ãƒ©ãƒ¼ãŒè‡ªåˆ†ãŸã¡ã®ã‚³ãƒ¼ãƒ‰ã«ã‚りã¾ã—ãŸã€‚

ç°¡å˜ãªæ–¹æ³•ã¯ã‚りã¾ã›ã‚“ã§ã—ãŸï¼šã‚¨ãƒ©ãƒ¼ã‚’一ã¤ãšã¤è§£æ±ºã—ã¦ã„ãå¿…è¦ãŒã‚りã¾ã—ãŸã€‚

本当ã«ä¸€èˆ¬çš„ã ã£ãŸã„ãã¤ã‹ã®ã‚«ãƒ†ã‚´ãƒªã¨ã€ãれらをã©ã®ã‚ˆã†ã«è§£æ±ºã—ãŸã‹ã‚’ã¾ã¨ã‚ã¾ã—ãŸï¼š

UIScreen

visionOSã«ã¯ã»ã¼å®Œå…¨ãªUIKitãŒã‚りã¾ã™ãŒã€ã„ãã¤ã‹ã®é‡è¦ãªéƒ¨åˆ†ãŒæ¬ ã‘ã¦ã„ã¾ã™ã€‚AppleãŒä½•å¹´ã‚‚å‰ã«iOSã§éžæŽ¨å¥¨ã¨å®£è¨€ã—ã¦ã„ãŸã™ã¹ã¦ã®ã‚³ãƒ¼ãƒ‰ã‚’削除ã—ãŸãŸã‚(技術的負債を引ãç¶™ãŽãŸããªã‹ã£ãŸã®ã ã¨æ€ã„ã¾ã™ï¼‰ã€ã‚ã‚‹ã„ã¯ã“ã“ã§ã¯æ„味をãªã•ãªã„ãŸã‚ã§ã™ã€‚UIScreenã¯å¾Œè€…ã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ä¸€ã¤ã§ã™ï¼šãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒé•·æ–¹å½¢ã§ã¯ãªã360度ã®çƒä½“ã‚’éŠã³å ´ã¨ã—ã¦æŒã¤ã“ã¨ã«ãªã‚‹ãŸã‚ã€ã‚¹ã‚¯ãƒªãƒ¼ãƒ³ã¨ã„ã†æ¦‚念ã¯ã‚‚ã¯ã‚„関係ãªã„ã®ã§ã™ã€‚

コードを確èªã—ãŸçµæžœã€UIScreenã¯ã»ã¨ã‚“ã©ã®å ´åˆã€ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã¨UIã®ã‚µã‚¤ã‚ºã‚’決ã‚ã‚‹ãŸã‚ã®åˆ¶ç´„ã‚’å–å¾—ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã—ã¦ãŠã‚Šã€ã‚¹ã‚¯ãƒªãƒ¼ãƒ³ã®ã‚¹ã‚±ãƒ¼ãƒ«ï¼ˆRetinaã‹ã©ã†ã‹ï¼‰ã‚’知るãŸã‚ã«ä½¿ç”¨ã—ã¦ã„ã‚‹ã“ã¨ãŒã‚ã‹ã‚Šã¾ã—ãŸã€‚ã“れã¯é‡è¦ã§ã™ã€‚ãªãœãªã‚‰ã€ã‚³ãƒ¼ãƒ‰å…¨ä½“ã§ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆï¼ˆãƒ•レームã®è¨­å®šï¼‰ã‚’使用ã—ã¦ã„ã‚‹ã‹ã‚‰ã§ã™ã€‚visionOSã§ã¯ãƒ‡ãƒ•ォルト値を返ã—ã€ä»–ã®ãƒ—ラットフォームã§ã¯å®Ÿéš›ã®UIScreenプロパティを返ã™ãƒ©ãƒƒãƒ‘ーを作æˆã—ã¾ã—ãŸï¼š

public class CraftScreen: NSObject {
    // MARK: - UIScreen emulation

    /// Acts similarly to `UIScreen.main`, but will be mocked on platforms like visionOS which don't have `UIScreen`
    public static var main: CraftScreen = CraftScreen()

    public var traitCollection: UITraitCollection {
        return Self.traitCollection
    }

    public var bounds: CGRect {
        return Self.bounds
    }

    public var scale: CGFloat {
        return Self.scale
    }

    // MARK: - New style accessors

    public static var traitCollection: UITraitCollection {
        #if os(visionOS)
        return UITraitCollection.current
        #else
        return UIScreen.main.traitCollection
        #endif
    }

    public static var userInterfaceStyle: UIUserInterfaceStyle {
        return Self.traitCollection.userInterfaceStyle
    }

    public static var bounds: CGRect {
        #if os(visionOS)
        return CGRect(x: 0, y: 0, width: 1024, height: 768)
        #else
        return UIScreen.main.bounds
        #endif
    }

    /// `UITraitCollection` can return different results on main and a background thread. We trust only the value on the main thread, therefore we try to cache it
    private static var _lastScale: CGFloat = 2.0
    public static var scale: CGFloat {
        if Thread.isMainThread {
            #if os(visionOS)
            let scale: CGFloat = UITraitCollection.current.displayScale
            #else
            let scale: CGFloat = UIScreen.main.scale
            #endif
            _lastScale = scale
            return scale
        } else {
            return _lastScale
        }
    }
}

基本的ã«ã€ã™ã¹ã¦ã®UIScreen.main.traitCollectionã®å‘¼ã³å‡ºã—ã‚’CraftScreen.main.traitCollectionã«ç½®ãæ›ãˆã¾ã—ãŸã€‚

プラットフォームサãƒãƒ¼ãƒˆ

マルãƒãƒ—ラットフォーム開発をサãƒãƒ¼ãƒˆã™ã‚‹ãŸã‚ã«ã€Craftã«ã¯éžå¸¸ã«ä¾¿åˆ©ãªæ‹¡å¼µæ©Ÿèƒ½ãŒå¤šæ•°ã‚りã¾ã™ã€‚ã»ã¼ã™ã¹ã¦ã®ä¸€èˆ¬çš„ãªåž‹ã«ã€æ¬¡ã®ã‚ˆã†ã«æ©Ÿèƒ½ã™ã‚‹é–¢æ•°ã‚»ãƒƒãƒˆãŒè¿½åŠ ã•れã¦ã„ã¾ã™ï¼š

extension Int {
  func onMac(_ value: Int) {
    return DeviceUtility.isMac ? value : self
  }
}

ã“れã«ã‚ˆã‚Šã€ã‚³ãƒ¼ãƒ‰ã«ãƒ‡ãƒ•ォルト値を記述ã—ã€æ¬¡ã®ã‚ˆã†ã«ãƒ—ラットフォーム固有ã®èª¿æ•´ã‚’ç°¡å˜ã«è¿½åŠ ã§ãã¾ã™ï¼š

let padding: Int = 16.onMac(8)

ã“れã¯Macã§å®Ÿè¡Œã•れるã¨8ã€ãれ以外ã§ã¯16ã‚’è¿”ã—ã¾ã™ã€‚

ã“ã®ã‚·ã‚¹ãƒ†ãƒ ã‚’Vision Proã‚’èªè­˜ã™ã‚‹ã‚ˆã†æ‹¡å¼µã—ã€å¯¾å¿œã™ã‚‹.onVision関数を追加ã—ã¾ã—ãŸï¼š

public enum PlatformType {
    case unsupported
    case iPadOS
    case iOS
    case macCatalyst
    case visionOS
}

static public var platformType : PlatformType {
    #if targetEnvironment(macCatalyst)
        return .macCatalyst
    #elseif os(visionOS)
        return .visionOS
    #else
    if UIDevice.current.userInterfaceIdiom == .pad {
        return .iPadOS
    } else if UIDevice.current.userInterfaceIdiom == .phone {
        return .iOS
    } else {
        return .unsupported
    }
    #endif
}

static public var isVision : Bool {
    return self.platformType == .visionOS
}

ã¾ãŸã€æ–°ã—ã„プラットフォームをèªè­˜ã—ã€ã™ã¹ã¦ã®ãƒ—ロパティを正ã—ã設定ã™ã‚‹ã‚ˆã†å†…部アナリティクスツールも拡張ã—ã¾ã—ãŸã€‚

サãƒãƒ¼ãƒˆã•れã¦ã„ãªã„ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢æ©Ÿèƒ½ã®é™¤åŽ»

visionOSã¯å°åˆ·ã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ãªã„ãŸã‚ã€ã‚¢ãƒ—リã‹ã‚‰å¯¾å¿œã™ã‚‹ã™ã¹ã¦ã®ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹å¿…è¦ãŒã‚りã¾ã—ãŸã€‚ã‚‚ã¡ã‚ã‚“ã€PDFã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¦å°åˆ·ã§ãるデãƒã‚¤ã‚¹ã«ãƒ•ァイルをé€ã‚‹ã“ã¨ã¯ã§ãã¾ã™ãŒã€ç¾åœ¨ã®å½¢ã§ã¯Vision Proã§ç›´æŽ¥å°åˆ·ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。

åŒæ§˜ã«ã€ãƒ—ラットフォームã¯é–‹ç™ºè€…ãŒã‚«ãƒ¡ãƒ©ã‚’使用ã™ã‚‹æ–¹æ³•ã‚’æä¾›ã—ã¦ã„ã¾ã›ã‚“。皮肉ãªã“ã¨ã«ã€Vision Proã¯Appleデãƒã‚¤ã‚¹ã®ä¸­ã§æœ€å¤šã®ã‚«ãƒ¡ãƒ©æ•°ã‚’æŒã£ã¦ã„ã¾ã™ðŸ™‚。ã™ã¹ã¦ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‹ã‚‰å†™çœŸã‚’撮るオプションを削除ã—ã€ãƒ¡ãƒ‡ã‚£ã‚¢ãƒ”ッカーã¨Unsplashã®ã‚ªãƒ—ションã ã‘を残ã—ã¾ã—ãŸã€‚

ç´°ã‹ã„修正

visionOSã‹ã‚‰æ¬ ã‘ã¦ã„ã‚‹ãã®ä»–ã®ã‚¯ãƒ©ã‚¹ã¨ãƒ—ロパティ:

  • UITextView.inputAssistantItem
  • UIScreenshotServiceDelegate
  • UIImagePickerController.QualityType.typeHigh
  • UIApplication.openURL(openã«æ”¹å)
  • CLAuthorizationStatus.authorizedAlways & CLLocation.requestAlwaysAuthorization()
  • CoreTelephonyフレームワーク
  • UIViewController.setNeedsStatusBarAppearanceUpdate()
  • UIFeedbackGenerator
  • UIWindow.keyWindow(ãšã£ã¨å‰ã‹ã‚‰éžæŽ¨å¥¨ï¼‰
  • UIViewController.keyboardDismissMode

ã“れらã¯ã™ã¹ã¦ã€å°ã•ãªã€ã¾ãŸã¯å¤§ããªæ©Ÿèƒ½å‰Šæ¸›ã§ç½®ãæ›ãˆã‚‹ã‹å›žé¿ã™ã‚‹ã“ã¨ãŒã§ãã¾ã—ãŸã€‚

美ã—ã„visionOSアプリã«ãªã‚‹ã¾ã§ã®é“ã®ã‚Š

ã“ã®ãƒ•ェーズを経ã¦ã€ã‚¢ãƒ—リã¯visionOS SDKã«å¯¾ã—ã¦ãƒ“ルドã—ã€Vision Proã§å®‰å®šã—ã¦å‹•作ã™ã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã—ãŸã€‚唯一ã®å•題ã¯ã€ãれãŒvisionOSらã—ã見ãˆãªã„ã“ã¨ã§ã—ãŸã€‚

ã‚‚ã¡ã‚ã‚“ã€visionOS SDKã«å¯¾ã—ã¦ãƒ“ルドã™ã‚‹ã ã‘ã§ã€iPadã‚¢ãƒ—ãƒªã¨æ¯”ã¹ã¦å¤šãã®åˆ©ç‚¹ãŒã™ã§ã«å¾—られã¾ã™ã€‚最も明白ãªã‚‚ã®ã¨ã—ã¦ã€ã‚¢ãƒ—リを自由ã«ãƒªã‚µã‚¤ã‚ºã§ãã¾ã™ã€‚プロダクトエンジニアãŒåŸºç¤Žä½œæ¥­ã‚’行ã£ã¦ã„ã‚‹é–“ã€ãƒ‡ã‚¶ã‚¤ãƒ³ãƒãƒ¼ãƒ ã¯ãƒ—ラットフォームã§ã‚¢ãƒ—ãƒªãŒæœ€çµ‚çš„ã«ã©ã®ã‚ˆã†ã«è¦‹ãˆã‚‹ã¹ãã‹ã‚’想åƒã™ã‚‹ã“ã¨ã«éžå¸¸ã«èˆˆå¥®ã—ã¦ã„ã¾ã—ãŸã€‚ã„ãã¤ã‹å復をé‡ã­ã€visionOSã§ãƒã‚¤ãƒ†ã‚£ãƒ–ã«è¦‹ãˆã€ã‹ã¤æ—¢å­˜ã®ã‚³ãƒ¼ãƒ‰ãƒ™ãƒ¼ã‚¹ã‹ã‚‰å®Ÿè£…ã—ã‚„ã™ã„親ã—ã¿ã‚„ã™ã„コンセプトã«åˆ°é”ã—ã¾ã—ãŸã€‚

ãƒã‚¤ãƒ©ã‚¤ãƒˆ

visionOSã¯ç›®ã‚’追跡ã—ã€è¦‹ã¦ã„るアイテムを画é¢ä¸Šã§é¸æŠžã™ã‚‹ãŸã‚ã®å„ªã‚ŒãŸãƒ¡ã‚«ãƒ‹ã‚ºãƒ ã‚’æä¾›ã—ã¾ã™ã€‚ã—ã‹ã—ã€ã‚·ã‚¹ãƒ†ãƒ ãŒè¦‹ã¦ã„ã‚‹è¦ç´ ã‚’ãƒã‚¤ãƒ©ã‚¤ãƒˆã™ã‚‹ã“ã¨ã§ç†è§£ã—ã¦ã„ã‚‹ã“ã¨ã‚’ä¿è¨¼ã—ãªã„å ´åˆã€ç¢ºä¿¡ã¯çªç„¶æ¶ˆãˆã¦ã—ã¾ã„ã¾ã™ã€‚UIButtonã®ã‚ˆã†ãªæ¨™æº–UIエレメントを使用ã—ã¦ã„れã°ã€ã“れã¯ç„¡æ–™ã§æ‰‹ã«å…¥ã‚Šã¾ã™ã€‚ã—ã‹ã—ç§ãŸã¡ã¯CraftãŒè‡ªä½œã—ãŸã‚³ãƒ¼ãƒ‰ã‚’ä¿¡ã˜ã¦ã„ã‚‹ã®ã§ã€Craftã®UIã®ã»ã¨ã‚“ã©ã¯ã‚·ãƒ³ãƒ—ルãªUIViewサブクラスã‹ã‚‰ã‚«ã‚¹ã‚¿ãƒ ãƒ¡ã‚¤ãƒ‰ã•れã¦ã„ã¾ã™ã€‚

大ããªåˆ©ç‚¹ãŒã‚りã¾ã—ãŸï¼šUIViewã‚’ãã®ã¾ã¾ä½¿ã†ä»£ã‚りã«ã€CraftTappableViewを使用ã—ã¦ã„ã¾ã™ã€‚ã“れã«ã‚ˆã‚Šã€ã‚¹ã‚¿ã‚¤ãƒ«ã‚ªãƒ–ジェクトã®è‡ªå‹•継承ã€å¤šãã®è¨­å®šå¯èƒ½ãªã‚¿ãƒƒãƒ—・クリック動作ãªã©ã®éžå¸¸ã«ä¾¿åˆ©ãªä»•組ã¿ãŒæä¾›ã•れã€å¸¸ã«ä½¿ç”¨ã—ã¦ã„ã¾ã™ã€‚幸ã„ãªã“ã¨ã«ã€ç”»é¢ä¸Šã®ã™ã¹ã¦ã®ã‚¤ãƒ³ã‚¿ãƒ©ã‚¯ãƒ†ã‚£ãƒ–ãªãƒœã‚¿ãƒ³ã¨ã‚ªãƒ–ジェクトã¯ã“ã®ã‚¯ãƒ©ã‚¹ã‹ã‚‰æ´¾ç”Ÿã—ã¦ã„ã‚‹ãŸã‚ã€ã‚¯ãƒ©ã‚¹ã«ã“ã®3行を追加ã™ã‚‹ã ã‘ã§ã€ã„ãŸã‚‹å ´æ‰€ã§ãƒŠã‚¤ã‚¹ãªãƒ›ãƒãƒ¼ã‚¨ãƒ•ェクトを実ç¾ã§ãã¾ã—ãŸï¼š

#if os(visionOS)
self.hoverStyle = UIHoverStyle(effect: .highlight)
#endif

ツールãƒãƒƒãƒ—

ç§ãŸã¡ã¯Catalystアプリケーションã§ã‚りã€iOSã¯ãƒ„ールãƒãƒƒãƒ—を長期間サãƒãƒ¼ãƒˆã—ã¦ã„ãªã‹ã£ãŸãŸã‚ã€ãƒã‚¤ãƒ³ãƒ†ã‚£ãƒ³ã‚°ãƒ‡ãƒã‚¤ã‚¹ã‚’æŒã¤ãƒ—ラットフォームã§ä½¿ç”¨ã™ã‚‹ç‹¬è‡ªã®ã‚½ãƒªãƒ¥ãƒ¼ã‚·ãƒ§ãƒ³ã‚’構築ã™ã‚‹å¿…è¦ãŒã‚りã¾ã—ãŸã€‚

visionOSã§ã¯ãƒ¬ã‚¬ã‚·ãƒ¼OSサãƒãƒ¼ãƒˆã¯å¿…è¦ãªãã€ã‚·ã‚¹ãƒ†ãƒ æä¾›ã®UITooltipInteractionを使用ã—ã€ã‚·ã‚¹ãƒ†ãƒ ã‚³ãƒ¼ãƒ«ã§ã‚°ãƒ­ãƒ¼ãƒãƒ«ã«ã‚³ãƒ¼ãƒ‰ã‚’ç½®ãæ›ãˆã‚‹ã“ã¨ãŒã§ãã¾ã—ãŸï¼š

システムæä¾›ã®ãƒ„ールãƒãƒƒãƒ—ã¨ãƒã‚¤ãƒ©ã‚¤ãƒˆï¼ˆã¾ã æœªèª¿æ•´ã®ãƒ„ールãƒãƒ¼å½¢çŠ¶ï¼‰

public var toolTip: String? {
    didSet {
        #if os(visionOS)
        self.addUITooltipInteractionIfNeeded()
        #endif
    }
}

private func addUITooltipInteractionIfNeeded() {
    if #available(iOS 15.0, macCatalyst 15.0, visionOS 1.0, *) {
        if let existingInteraction = interactions.compactMap({ $0 as? UIToolTipInteraction }).first {
            self.removeInteraction(existingInteraction)
        }

        // Add new tooltip interaction if there's a new tooltip text
        if let toolTip: String = toolTip {
            let newInteraction = UIToolTipInteraction(defaultToolTip: toolTip)
            self.addInteraction(newInteraction)
        }
    }
}

ダークモードã¨ãƒ©ã‚¤ãƒˆãƒ¢ãƒ¼ãƒ‰

visionOSã«ã¯å°‚用ã®ãƒ€ãƒ¼ã‚¯ãƒ¢ãƒ¼ãƒ‰ã¨ãƒ©ã‚¤ãƒˆãƒ¢ãƒ¼ãƒ‰ãŒã‚りã¾ã›ã‚“。没入モードã®ã‚«ãƒ©ãƒ¼ã‚’ダークã¾ãŸã¯ãƒ©ã‚¤ãƒˆã«è¨­å®šã§ãã¾ã™ãŒã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェースã¯ç’°å¢ƒã«è‡ªå‹•çš„ã«é©å¿œã™ã‚‹ç¾Žã—ã„ガラスマテリアルã®ã¾ã¾ã§ã™ã€‚

Craftã¯ãƒ€ãƒ¼ã‚¯ãƒ¢ãƒ¼ãƒ‰ã¨ãƒ©ã‚¤ãƒˆãƒ¢ãƒ¼ãƒ‰ã®ä¸¡æ–¹ã‚’サãƒãƒ¼ãƒˆã—ã€ã‚¢ãƒ—リ内ã§ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã“れをオーãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚Vision Proã§ã¯ã“ã®æ©Ÿèƒ½ã‚’å†è€ƒã™ã‚‹å¿…è¦ãŒã‚りã¾ã—ãŸã€‚ç§ãŸã¡ã®æ—¢å­˜ã®ãƒ€ãƒ¼ã‚¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェースãŒç›®æŒ‡ã™ã‚‚ã®ã«æœ€ã‚‚è¿‘ã„ã¨åˆ¤æ–­ã—ã€ã‚¢ãƒ—リã®ã‚°ãƒ­ãƒ¼ãƒãƒ«ãªå¤–観をダークã«ã‚ªãƒ¼ãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã™ã‚‹ã“ã¨ã‹ã‚‰å§‹ã‚ã¾ã—ãŸã€‚

image

ã“れã«ã‚ˆã‚ŠãƒŠã‚¤ã‚¹ãªã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェースã«ãªã‚Šã¾ã—ãŸãŒã€ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã¯ç´™ã®ç›´æŽ¥ã®å¾Œç¶™ã¨ã—ã¦ã€ç™½ãã‚ã‚‹ã“ã¨ã‚‚許å¯ã•れるã¹ãã ã¨æ„Ÿã˜ã¾ã—ãŸã€‚

XMLã§UI設定を定義ã—ã€ãƒ—ラットフォームã«åˆã‚ã›ã¦ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã•れるモジュールå¼è¨­å®šã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェースãŒã‚りã¾ã™ã€‚visionOSプラットフォームã®ã‚µãƒãƒ¼ãƒˆã‚’追加ã—ã€ãƒ†ãƒ¼ãƒžè¨­å®šã‚’ダークã¨ãƒ©ã‚¤ãƒˆã®ãƒãƒªã‚¢ãƒ³ãƒˆã®ã¿ã«å¤‰æ›´ã—ã¾ã—ãŸï¼ˆè‡ªå‹•オプションを削除)。

ã—ã‹ã—難ã—ã„éƒ¨åˆ†ã¯æ¬¡ã®ã‚¹ãƒ†ãƒƒãƒ—ã§ã—ãŸï¼šoverrideUserInterfaceStyleã§UIをダークモードã«å¼·åˆ¶ã—ãªãŒã‚‰ã€ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’ライトモードã§è¡¨ç¤ºã™ã‚‹ã«ã¯ã©ã†ã™ã‚Œã°ã‚ˆã„ã‹ï¼Ÿã•ã‚‰ã«æ‚ªã„ã“ã¨ã«ã€ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã ã‘ã§ãªãã€ã‚¿ãƒ–プレビューã€ç›®æ¬¡ã®ãƒ„ールãƒãƒƒãƒ—ã€ãƒ•ァイルブラウザã€ãƒ›ãƒ¼ãƒ ç”»é¢ã€ãã—ã¦UIã®ä¸€éƒ¨ã‚‚æ›´æ–°ã™ã‚‹å¿…è¦ãŒã‚りã¾ã—ãŸã€‚ライトãªãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆèƒŒæ™¯ã¨ãƒ€ãƒ¼ã‚¯ãªãƒœãƒˆãƒ ãƒ„ールãƒãƒ¼ã®çµ„ã¿åˆã‚ã›ãŒè‰¯ã見ãˆãªã„ã¨æ„Ÿã˜ãŸãŸã‚ã§ã™ã€‚

解決策ã¯å¤§å¤‰ãªä½œæ¥­ã‚’å¿…è¦ã¨ã—ã¾ã—ãŸã€‚ã™ã§ã«è¿°ã¹ãŸCraftTappableViewオブジェクトã¯pageStyleã¨å‘¼ã°ã‚Œã‚‹ã‚‚ã®ã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚ã“れã¯ç§ãŸã¡ãŒUITraitCollectionã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¨è€ƒãˆã‚‹ã“ã¨ãŒã§ãã¾ã™ï¼šã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã®ãƒ–ロックやボタンãªã©ã®ã‚ªãƒ–ジェクトãŒã©ã®ã‚ˆã†ã«è¦‹ãˆã‚‹ã‹ã‚’決定ã™ã‚‹è‰²ã€ã‚¹ã‚¿ã‚¤ãƒ«ã€ãƒ•ォントã®ã‚»ãƒƒãƒˆã§ã™ã€‚pageStyleã¯ç¾åœ¨ã®ãƒ†ãƒ¼ãƒžã«åŸºã¥ã„ã¦æ§‹ç¯‰ã•れã€ã‚µãƒ–ビューã«è‡ªå‹•çš„ã«ç¶™æ‰¿ã•れã¾ã™ã€‚変更もç§ãŸã¡ã®ãƒ“ューã«ã‚ˆã£ã¦è‡ªå‹•çš„ã«ä¼æ’­ã•れã¾ã™ã€‚ãã®ãŸã‚ã€pageStyleã¯ãƒ€ãƒ¼ã‚¯ãƒ¢ãƒ¼ãƒ‰ç”¨ã®è‰²ã‚’å«ã‚“ã§ã„ã¾ã—ãŸã€‚エディター用ã«contentPageStyleã‚‚å°Žå…¥ã—ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒè¨­å®šã—ãŸå¤–観ã«åˆã‚ã›ã¦å¤‰æ›´ã•れãŸã‚ªãƒªã‚¸ãƒŠãƒ«ã®pageStyleã®ãƒãƒªã‚¢ãƒ³ãƒˆã‚’å«ã¿ã¾ã—ãŸã€‚

var contentPageStyle : BlockModelPageStyle? {
    var retVal : BlockModelPageStyle? =  BlockPageStyleAPI.sharedInstance.styleForDescriptor(self.mainBlockModel?.pageStyleToUse) ?? BlockPageStyleAPI.sharedInstance.defaultStyle
    if retVal?.scaleFactor != self.scaleFactor {
        retVal = retVal?.duplicate(withScaleFactor: self.scaleFactor)
    }

    if DeviceUtility.isVision {
        let forceUserInterfaceStyle: UIUserInterfaceStyle = {
            switch OnDeviceStorage.sharedInstance.appearaÿÿnceUserInterfaceStyle {
                case 2: return .dark
                default: return .light
            }
        }()
        if retVal?.forceUserInterfaceStyle != forceUserInterfaceStyle {
            retVal = retVal?.duplicate(withForceUserInterfaceStyle: forceUserInterfaceStyle)
        }
    }
    return retVal
}

ã‚ã¨ã¯ã€è¨­å®šã«å応ã•ã›ãŸã„ビューã«é€šå¸¸ã®pageStyleã®ä»£ã‚りã«ã“ã®contentPageStyleを渡ã—ã€ç’°å¢ƒè¨­å®šãŒå¤‰æ›´ã•れãŸã¨ãã«ç™ºè¡Œã™ã‚‹NSNotificationã®ãƒªã‚¹ãƒŠãƒ¼ã‚’追加ã™ã‚‹ã ã‘ã§ã—ãŸã€‚

UIã‚’ã™ã¹ã¦ç¢ºèªã—ã¦ã€ãƒ©ã‚¤ãƒˆãƒãƒªã‚¢ãƒ³ãƒˆã‚’表示ã™ã¹ãã¨æ„Ÿã˜ãŸç®‡æ‰€ã§ã“ã®pageStyleを上書ãã™ã‚‹å¿…è¦ãŒã‚りã¾ã—ãŸã€‚ã“れã«ã‚ˆã£ã¦å¤šãã®èª²é¡ŒãŒç”Ÿã˜ã¾ã—ãŸã€‚ページ読ã¿è¾¼ã¿ã®ãŸã³ã«ä½•百回も呼ã³å‡ºã•れる関数ã‹ã‚‰ãƒ‡ã‚£ã‚¹ã‚¯ãƒ™ãƒ¼ã‚¹ã®å€¤ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã®ã¯è‰¯ã„アイデアã§ã¯ãªãã€ã¾ãŸã€ã“れらã®ã‚¯ãƒ©ã‚¹ãŒSwiftモジュールã‹ã‚‰å¸¸ã«ç›´æŽ¥ã‚¢ã‚¯ã‚»ã‚¹ã§ãã‚‹ã‚ã‘ã§ã‚‚ã‚りã¾ã›ã‚“ã§ã—ãŸã€‚

ガラスマテリアル

Craftã¯æ—¢ã«ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã®èƒŒæ™¯è‰²ã«å¤šãã®ä½œæ¥­ãŒæ–½ã•れã¦ã„ã¾ã™ã€‚ドキュメントã®èƒŒæ™¯ç”»åƒã¾ãŸã¯ã‚¹ãƒšãƒ¼ã‚¹ãƒ—ロファイル画åƒã®æ‹¡å¼µãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’使用ã—ãŸUIEffectViewã€è‰²ã€ã‚°ãƒ©ãƒ‡ãƒ¼ã‚·ãƒ§ãƒ³ã®çµ„ã¿åˆã‚ã›ã‚’使用ã—ã¦ã€ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã«å°‘ã—スパイスを加ãˆã¦ã„ã¾ã™ã€‚

visionOSã§ã¯OSãŒæä¾›ã™ã‚‹ãƒ”ュアãªã‚¬ãƒ©ã‚¹ãƒžãƒ†ãƒªã‚¢ãƒ«ã®ã¿ã‚’使用ã™ã‚‹ã“ã¨ã«ã—ã¾ã—ãŸã€‚ãã®ãŸã‚ã«ã€ä»–ã®ãƒ—ラットフォームã§ã“ã®åŠ¹æžœã‚’å®Ÿç¾ã™ã‚‹ãŸã‚ã«é…ç½®ã—ãŸã™ã¹ã¦ã®ãƒ“ューをオフã«ã—ã€åŸºæœ¬çš„ã«é€æ˜ŽãªèƒŒæ™¯ã‚’使用ã—ã¦ã€æ®‹ã‚Šã¯OSã«ä»»ã›ã‚‹ã“ã¨ã«ã—ã¾ã—ãŸã€‚

パディングã¨ãƒœã‚¿ãƒ³ã®å½¢çж

è¿‘ã¥ã„ã¦ãã¾ã—ãŸãŒã€ã‚¢ãƒ—リã¯ãƒ—ラットフォーム上ã®ä»–ã®ã‚¢ãƒ—ãƒªã¨æ¯”ã¹ã¦ã¾ã å¯†åº¦ãŒé«˜ã見ãˆã¾ã—ãŸã€‚トップツールãƒãƒ¼ã‹ã‚‰å§‹ã‚ã¦ã€ãƒ‡ã‚¶ã‚¤ãƒ³ã®ã‚µã‚¤ã‚ºã«åˆã‚ã›ã‚‹ãŸã‚ã«.onVisionコンディションを使用ã—ã¦ã™ã¹ã¦ã®ãƒ‘ディングを調整ã—ã¾ã—ãŸã€‚

image

調整ã•れãŸãƒ„ールãƒãƒ¼ã€‚サイドãƒãƒ¼ã«ã¯ã¾ã å…ƒã®ã‚µã‚¤ã‚ºãŒæ®‹ã£ã¦ã„ã‚‹ç‚¹ã«æ³¨ç›®ã€‚

レイヤーã«.cornerRadiusを追加ã™ã‚‹ã“ã¨ã§ã€visionOSã¯ã»ã¨ã‚“ã©ã®å ´åˆã€æ­£ã—ã„ホãƒãƒ¼ãƒ•ォームを自動的ã«é¸æŠžã—ã¾ã—ãŸãŒã€ã‚¯ãƒªãƒƒã‚¯å¯èƒ½ãªã‚ªãƒ–ジェクトã®å½¢çŠ¶ã‚’æ±ºå®šã™ã‚‹ã‚µãƒ–ビューを使用ã—ã¦ã„ãŸä¸€éƒ¨ã®ã‚±ãƒ¼ã‚¹ã§ã¯ã€æ‰‹å‹•ã§ãƒ›ãƒãƒ¼ã‚·ã‚§ã‚¤ãƒ—を調整ã™ã‚‹å¿…è¦ãŒã‚りã¾ã—ãŸï¼š

if #available(iOS 17.0, *) {
    self.closeButton.hoverStyle = .init(shape: .rect(cornerRadius: 8))
}

タブãƒãƒ¼ã®é«˜ã•ã€ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚¨ãƒƒã‚¸ã‹ã‚‰ã®ãƒ‘ディングã€ãƒœã‚¿ãƒ³é–“ã®ãƒ‘ディングãªã©ã‚’増加ã—ã¾ã—ãŸã€‚カスタムツールãƒãƒ¼ã®å®Ÿè£…を使用ã—ã¦ãŠã‚Šã€ã“ã‚Œã‚‰ã®æ•°å€¤ã‚’定数ã¨ã—ã¦æŠ½å‡ºã—ãŸå„ªã‚ŒãŸæ‹¡å¼µå¯èƒ½ãªã‚³ãƒ¼ãƒ‰ãŒæ—¢ã«ã‚ã£ãŸãŸã‚ã€ä»–ã®ãƒ—ラットフォームã§ã®æ–¹æ³•ã¨åŒæ§˜ã«ã€ãれらã«onVisionモディファイアを追加ã™ã‚‹ã ã‘ã§ã‚ˆã‹ã£ãŸã§ã™ï¼š

var preferredWidth : CGFloat { return 40.onMac(36).onVision(44) }

色ã«ã‚‚åŒã˜ãƒ†ã‚¯ãƒ‹ãƒƒã‚¯ã‚’使用ã—ã¾ã—ãŸï¼š

self._bgView.backgroundColor = UIColor.clear.onVision(UIColor.white.withAlphaComponent(0.06))

入力方法

Vision Proã«ã¯3ã¤ã®ç•°ãªã‚‹å…¥åŠ›æ–¹æ³•ãŒã‚りã¾ã™ï¼š

  • ピンãƒã‚¸ã‚§ã‚¹ãƒãƒ£ãƒ¼ã«ã‚ˆã‚‹ã‚¢ã‚¤ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã€‚ ã‚‚ã®ã‚’見ã¦ã€æŒ‡ã§ãƒ”ンãƒã—ã¦ã€Œã‚¯ãƒªãƒƒã‚¯ã€ã—ã¾ã™ã€‚システムæä¾›ã®ãƒ›ãƒãƒ¼ã‚¨ãƒ•ェクトãŒã‚りã¾ã™ãŒã€ã‚¢ãƒ—リã¯ãƒ›ãƒãƒ¼ã‚¤ãƒ™ãƒ³ãƒˆã‚’å—ã‘å–りã¾ã›ã‚“。
  • ダイレクトフィンガーコントロール。 アプリを自分ã«è¿‘ã¥ã‘ã¦ã€ã¾ã‚‹ã§æœ¬ç‰©ã®ã‚ˆã†ã«æŒ‡ã§ãƒœã‚¿ãƒ³ã‚’押ã—ã¾ã™ã€‚ã“ã®æ–¹æ³•ã¯ã‚¹ãƒ¼ãƒ‘ークールãªãƒ›ãƒãƒ¼ã‚¨ãƒ•ェクトもæä¾›ã—ã¾ã™

ホãƒãƒ¼ã‚¸ã‚§ã‚¹ãƒãƒ£ãƒ¼ã§å°‘ã—éŠã‚“ã§ã¿ã‚‹

  • トラックパッドã«ã‚ˆã‚‹é–“接コントロール。 接続ã•れãŸMacã®ãƒˆãƒ©ãƒƒã‚¯ãƒ‘ッドやペアリングã—ãŸBluetooth トラックパッドアクセサリを使用ã—ã¦ã€iPadã‚„Macã®ã‚ˆã†ã«ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェースをコントロールã™ã‚‹ã‚«ãƒ¼ã‚½ãƒ«ã‚’使ãˆã¾ã™ã€‚ã“れã¯iPadã‚„Macã¨ã¾ã£ãŸãåŒã˜ã‚ˆã†ã«æ©Ÿèƒ½ã—ã¾ã™ã€‚

タブã®å®Ÿè£…ã«ãŠã„ã¦ã‚¢ã‚¤ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã‚’より使ã„ã‚„ã™ãã™ã‚‹ãŸã‚ã«ã€ã„ãã¤ã‹ã®å°ã•ãªå¤‰æ›´ã‚’加ãˆã¾ã—ãŸã€‚通常ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã‚¿ãƒ–ã«ãƒ›ãƒãƒ¼ã—ãŸã¨ãã«é–‰ã˜ã‚‹ãƒœã‚¿ãƒ³ã‚’表示ã—ã€éžã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªã‚¿ãƒ–ã‚’é–‰ã˜ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚アイコントロールã§ã¯visionOSãŒãƒ›ãƒãƒ¼ã‚¤ãƒ™ãƒ³ãƒˆã‚’æä¾›ã—ãªã„ãŸã‚ã€é–‰ã˜ã‚‹ãƒœã‚¿ãƒ³ã®å¯è¦–性を設定ã§ããšã€ãƒœã‚¿ãƒ³ãŒè¡¨ç¤ºã•れã¾ã›ã‚“ã§ã—ãŸã€‚ã—ã‹ã—ã€ã‚¿ãƒ–ã®å·¦å´ã‚’見ã¦ãƒ”ンãƒã—ã¦ã‚‚当然閉ã˜ã‚‹ã“ã¨ã¯ã§ãã¾ã—ãŸã€‚ã“れã¯è‰¯ããªã‹ã£ãŸãŸã‚ã€ãƒã‚¤ãƒ³ã‚¿ãƒ¼ã‚’検出ã—ãªã„visionOSプラットフォームã§ã¯é–‰ã˜ã‚‹ãƒœã‚¿ãƒ³ã‚’完全ã«å»ƒæ­¢ã—ã¾ã—ãŸã€‚

3Dパãƒãƒ«

開発中ã«è¡Œã£ãŸæœ€ã‚‚興味深ã„ã“ã¨ã®ä¸€ã¤ã¯ã€ã™ã¹ã¦ã®ãƒ‘ãƒãƒ«ã‚’3D空間ã«ç§»å‹•ã•ã›ã‚‹ã“ã¨ã§ã™ã€‚

Craftã«ã¯ãƒ‘ãƒãƒ«ã‚°ãƒ«ãƒ¼ãƒ—ã¨å‘¼ã¶ãƒŠã‚¤ã‚¹ãªã‚¯ãƒ©ã‚¹ãŒã‚りã¾ã™ã€‚ã“ã®ã‚¯ãƒ©ã‚¹ã¯ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã®ä¸Šã«ã‚³ãƒ³ãƒ†ãƒ³ãƒ„を表示ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã—ã¦ãŠã‚Šã€ãƒ¢ãƒ¼ãƒ€ãƒ«ãƒ“ューã®ãƒ—レゼンテーションã€ãƒãƒƒãƒ—オーãƒãƒ¼ã€ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆãƒ¡ãƒ‹ãƒ¥ãƒ¼ã®ä¸€éƒ¨ã‚’ç½®ãæ›ãˆã¦ã„ã¾ã™ã€‚OSã®å®Ÿè£…ã®ã„ãšã‚Œã‹ã«è¦‹ãˆã‚‹ã»ã©æŸ”軟ã§ã‚りãªãŒã‚‰ã€UIKitã®ãƒãƒªã‚¢ãƒ³ãƒˆã‚ˆã‚Šã‚‚柔軟ã«ã‚µã‚¤ã‚ºã¨é…ç½®ãŒã§ãã¾ã™ã€‚ã¾ãŸã€ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã‚’ç½®ãæ›ãˆã‚‹ã¨ãã®ãƒŠã‚¤ã‚¹ãªãƒˆãƒ©ãƒ³ã‚¸ã‚·ãƒ§ãƒ³ã‚‚ã‚りã¾ã™ï¼šè‡ªå‹•çš„ã«æ–°ã—ã„サイズã«ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã—ã¾ã™ã€‚

ã“ã®ã‚¯ãƒ©ã‚¹ã¯ã‚¢ãƒ—リ全体ã§ä½¿ç”¨ã—ã¦ã„ã‚‹ãŸã‚ã€å°‘ã—3Dエフェクトをé©ç”¨ã™ã‚‹ã“ã¨ã¯ç†ã«ã‹ãªã£ã¦ã„ã¾ã—ãŸã€‚

ã—ã‹ã—ã€ã©ã®ã‚ˆã†ã«ï¼Ÿ

Appleã¯visionãŒæä¾›ã™ã‚‹ã»ã¼ã™ã¹ã¦ã®ã‚‚ã®ã‚’UIKitã‹ã‚‰ã‚¢ã‚¯ã‚»ã‚¹ã§ãるよã†ã«ã™ã‚‹ç´ æ™´ã‚‰ã—ã„仕事をã—ã¾ã—ãŸãŒã€Zオフセットã¯ãã®ä¸€ã¤ã§ã¯ã‚りã¾ã›ã‚“ã§ã—ãŸã€‚ã—ã‹ã—ã€SwiftUIã‹ã‚‰å®Ÿç¾ã™ã‚‹ã“ã¨ãŒã§ãã¾ã—ãŸã€‚ç§ãŸã¡ã¯ã¾ã Craftã§SwiftUIを使用ã—ã¦ã„ãªã‹ã£ãŸãŸã‚ã€ã“れも新ã—ã„領域ã§ã—ãŸã€‚

ã‚¢ã‚¤ãƒ‡ã‚¢ã¯æ¬¡ã®ã¨ãŠã‚Šã§ã™ï¼š

  1. SwiftUIビューをUIKitã«åŸ‹ã‚込む
  2. SwiftUIビューã§.offset(z: 25)を調整ã—ã¦ã€3D空間ã§ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«è¿‘ã¥ã‘ã‚‹
  3. ã“ã®SwiftUIビューã«UIKitビューを埋ã‚込む

テストビューを作æˆã—ãŸã¨ã“ã‚ã€ã†ã¾ãã„ãã¾ã—ãŸï¼ã‚ã¨ã¯ã€ã“ã®ã™ã¹ã¦ã®å¤§å¤‰ãªä½œæ¥­ã‚’行ã†UIKitビューを作æˆã—ã€ãƒ‘ãƒãƒ«ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã‚’ã“ã®ãƒ“ューã®ã‚µãƒ–ビューã¨ã—ã¦è¿½åŠ ã—ã€3番目ã®ãƒã‚¤ãƒ³ãƒˆã®UIKitビューã«å®Ÿéš›ã«è¿½åŠ ã•れるã“ã¨ã‚’確èªã™ã‚‹ã ã‘ã§ã‚ˆã‹ã£ãŸã§ã™ã€‚

#if os(visionOS)

// +-----------------------------------------------+
// | CraftPanelRaisedContainerView                 |
// |  +------------------------------------------+ |
// |  | UIHostingController                      | |
// |  |  +-------------------------------------+ | |
// |  |  | RaisedView (SwiftUI)                | | |
// |  |  |  +-------------------------------+  | | |
// |  |  |  | UIKitEmbedderView             |  | | |
// |  |  |  | (SwiftUI)                     |  | | |
// |  |  |  |  +-------------------------+  |  | | |
// |  |  |  |  | RaisedViewUIKitContents |  |  | | |
// |  |  |  |  +-------------------------+  |  | | |
// |  |  |  +-------------------------------+  | | |
// |  |  +-------------------------------------+ | |
// |  +------------------------------------------+ |
// +-----------------------------------------------+

/// Public interface. DO NOT USE `addSubview`! USE `addRisedSubview` instead!
public class CraftPanelRaisedContainerView: UIView, RaisedViewProtocol {
    let embeddedHostingViewController: UIHostingController<RaisedView> = UIHostingController(rootView: RaisedView(level: 0))

    init() {
        super.init(frame: .zero)
        self.embeddedHostingViewController.sizingOptions = [.intrinsicContentSize, .preferredContentSize]
        self.addSubview(self.embeddedHostingViewController.view)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    public override func layoutSubviews() {
        super.layoutSubviews()
        self.updateLevel()
        self.embeddedHostingViewController.view.frame = self.bounds
    }

    func updateLevel() {
        guard
            let window: UIWindow = self.window,
            self.embeddedHostingViewController.rootView.level != CraftPanelRaisedContainerViewRegistry.shared.level(for: window)
        else { return }

        let newRaisedView: RaisedView = RaisedView(level: CraftPanelRaisedContainerViewRegistry.shared.level(for: window))
        self.embeddedHostingViewController.rootView.contents.subviews.forEach { v in
            v.removeFromSuperview()
            newRaisedView.contents.addSubview(v)
        }
        self.embeddedHostingViewController.rootView = newRaisedView
    }

    public func addRaisedSubview(_ view: UIView) {
        self.embeddedHostingViewController.rootView.contents.addSubview(view)
    }
}

/// SwiftUI view which is responsible for the Z axis transformation
struct RaisedView: View {
    let contents: RaisedViewUIKitContents = RaisedViewUIKitContents()
    var level: Int
    var contentCornerRadius: CGFloat = 20

    var body: some View {
        UIKitEmbedderView(embeddedView: contents)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .glassBackgroundEffect(in: RoundedRectangle(cornerSize: CGSize(width: contentCornerRadius, height: contentCornerRadius)))
            .offset(z: CGFloat(level * 25)) // This will move the view to the 3D space
    }
}

/// This view will contain the actual subviews for the whole hierarchy
class RaisedViewUIKitContents: UIView { }

/// SwiftUI view which embeds the `CraftPanelRaisedContainerViewController`
struct UIKitEmbedderView: UIViewControllerRepresentable {
    typealias UIViewControllerType = CraftPanelRaisedContainerViewController
    let embeddedView: UIView

    func makeUIViewController(context: Context) -> CraftPanelRaisedContainerViewController {
        return CraftPanelRaisedContainerViewController()
    }

    func updateUIViewController(_ uiViewController: CraftPanelRaisedContainerViewController, context: Context) {
        uiViewController.addContainedView(embeddedView)
    }
}

/// `UIKitEmbedderView` will embed this controller and add it's `embeddedView` to a subview of this
class CraftPanelRaisedContainerViewController: UIViewController {
    var containedView: UIView?

    func addContainedView(_ view: UIView) {
        self.containedView = view
        self.view.addSubview(view)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        self.containedView?.frame = self.view.bounds
    }
}

#else

public class CraftPanelRaisedContainerView: UIView, RaisedViewProtocol {
    public func addRaisedSubview(_ view: UIView) {
        self.addSubview(view)
    }
}

#endif

ã“れãŒå®Ÿéš›ã®è¦‹ãŸç›®ã§ã™ï¼š

image

3Dç©ºé–“ã«æµ®ã‹ã¶ãƒ‘ãƒãƒ«

é¢ç™½ã„サイドストーリーを追加ã•ã›ã¦ãã ã•ã„:システムã®ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆãƒ¡ãƒ‹ãƒ¥ãƒ¼ãŒç§ãŸã¡ã®50ptオフセットよりもウィンドウã«è¿‘ã„ã“ã¨ã«æ°—ã¥ãã¾ã—ãŸã€‚ã§ã¯ã€ã“ã“ã§Z軸ã®è·é›¢ã‚’ã©ã®ã‚ˆã†ã«æ¸¬å®šã—ã¾ã™ã‹ï¼Ÿç°¡å˜ã§ã™ï¼æ˜”ã®ã‚ˆã†ã«æŒ‡ã‚’使ã£ã¦ç©ºé–“ã§æ¸¬ã‚Œã°ã„ã„ã‚“ã§ã™ï¼ðŸ˜‰ è·é›¢ã¯ã ã„ãŸã„åŠåˆ†ã«è¦‹ãˆãŸã®ã§ã€å€¤ã‚’åŠåˆ†ã«ã—ã¦åˆã‚ã›ã¾ã—ãŸã€‚

ã“ã“ã§æ³¨æ„ã™ã¹ã点ãŒã‚りã¾ã™ï¼šã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã«è¿½åŠ ã•れãŸã‚¿ãƒƒãƒ—リスナーã¯ã€ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãƒ¬ãƒ™ãƒ«ã‚ˆã‚Šä¸Šã«è¡¨ç¤ºã•れるãŸã‚ã€æµ®ã上ãŒã£ãŸãƒ“ューã§ã¯ç™ºç«ã—ã¾ã›ã‚“。注æ„ã—ã¦ãã ã•ã„ï¼

色

多ãã®æ™‚間を費やã—ãŸå•題ã®ä¸€ã¤ã¯ã€visionOSã§UIColorãŒã©ã®ã‚ˆã†ã«ç•°ãªã‚‹å‹•作をã™ã‚‹ã‹ã‚’ç†è§£ã—修正ã™ã‚‹ã“ã¨ã§ã—ãŸã€‚ç§ãŸã¡ã®UIコードã®ä¸€éƒ¨ã¯ã€ãƒ€ãƒ¼ã‚¯èƒŒæ™¯ã‚’æŒã¤ãƒœã‚¿ãƒ³ã®ãƒ©ãƒ™ãƒ«è‰²ã‚’設定ã™ã‚‹ãŸã‚ã«UIColor.systemBackgroundを使用ã—ã¦ã„ã¾ã—ãŸï¼ˆãƒ©ã‚¤ãƒˆãƒ¢ãƒ¼ãƒ‰ã§ã¯æ˜Žã‚‹ã表示ã•れã¦ã„ãŸï¼‰ã€‚Vision Proã§ã¯æ®‹å¿µãªãŒã‚‰ã€ã“ã®å®šæ•°ãŒå¤šãã®å ´åˆã«é€æ˜Žè‰²ã‚’è¿”ã™ãŸã‚ã€ã“れらã®ãƒ©ãƒ™ãƒ«ãŒæ¶ˆãˆã¦ã„ã¾ã—ãŸã€‚

ã‚‚ã†ä¸€ã¤ã®ä¼¼ãŸã‚ˆã†ãªå•題ã¯ã€UIColor.labelãŒèƒŒæ™¯è‰²ã«è‡ªå‹•çš„ã«é©å¿œã™ã‚‹ã“ã¨ã§ã™ã€‚ãã—ã¦ã€ãれã¯é…ç½®ã—ãŸå ´æ‰€ã”ã¨ã«æ­£ã—ã„色ã§è¡¨ç¤ºã•れるã“ã¨ã§è¡Œã‚れã¾ã™ã€‚å°‘ãªãã¨ã‚‚ã“れãŒç†è«–ã§ã™ãŒã€æ®‹å¿µãªãŒã‚‰ç§ãŸã¡ã«ã¨ã£ã¦ã¯ã€ç™½ã„背景ã«ç™½è‰²ã§è¡¨ç¤ºã•れるã“ã¨ã‚‚ã‚りã¾ã—ãŸã€‚ã•ã‚‰ã«æ‚ªã„ã“ã¨ã«ã€ãƒ‡ãƒãƒƒã‚¬ãƒ¼ã§ãã®å€¤ã‚’表示ã™ã‚‹ã¨ã€å¸¸ã«å…ƒã®ãƒ€ãƒ¼ã‚¯è‰²ãŒè¡¨ç¤ºã•れã¾ã™ã€‚

アクセシビリティ

ã™ã¹ã¦ã®Appleプラットフォームã¨åŒæ§˜ã«ã€visionOSも充実ã—ãŸã‚¢ã‚¯ã‚»ã‚·ãƒ“リティオプションã®ãƒªã‚¹ãƒˆã‚’æä¾›ã—ã¦ã„ã¾ã™ã€‚コントラストを高ã‚ãŸçŠ¶æ…‹ã€ãƒœã‚¿ãƒ³ã‚·ã‚§ã‚¤ãƒ—を有効ã«ã—ãŸçŠ¶æ…‹ã€ãã®ä»–ã™ã¹ã¦ã®ã‚ªãƒ—ションã§ã‚¢ãƒ—リを確èªã™ã‚‹ã“ã¨ãŒéžå¸¸ã«é‡è¦ã§ã™ã€‚コントラストを高ã‚ãŸãƒ¢ãƒ¼ãƒ‰ã§ä¸€éƒ¨ã®è¨­å®šãƒ©ãƒ™ãƒ«ãŒæ¬ ã‘ã¦ã„る箇所を見ã¤ã‘ã¾ã—ãŸã€‚

image

ã¾ã¨ã‚

振り返ã£ã¦ã¿ã‚‹ã¨ã€ã‚¢ãƒ—リをvisionOSã«ç§»æ¤ã™ã‚‹ã«ã¯å¤§ããªåŠªåŠ›ãŒå¿…è¦ã§ã—ãŸãŒã€äºˆæƒ³ã¨æ¯”ã¹ã‚‹ã¨éžå¸¸ã«ç°¡å˜ã§ã€æ¯”較的ã‚ã‹ã‚Šã‚„ã™ã„ã‚‚ã®ã§ã—ãŸã€‚ã»ã¨ã‚“ã©ã™ã¹ã¦ã®ã‚‚ã®ãŒã™ãã«æ©Ÿèƒ½ã—ã€OSã¯ç¾Žã—ã„デフォルトをæä¾›ã—ã¦ãŠã‚Šã€ãƒ—ラットフォームã«åˆã‚ã›ã‚‹ãŸã‚ã«ã‚ˆã‚Šå°è¦æ¨¡ãªèª¿æ•´ã‚’行ã†ã ã‘ã§ã‚ˆã‹ã£ãŸã§ã™ã€‚ç§ãŸã¡ã¯ã“ã®ã‚¿ãƒ¼ã‚²ãƒƒãƒˆã‚’メインコードベースã«ç¶­æŒã—ã€é€šå¸¸ã®ãƒ—ラットフォームã¨åŒæ§˜ã«Craftã®æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’リリースã§ãã‚‹ã¨è€ƒãˆã¦ã„ã¾ã™ã€‚

Apple Vision Proãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®Craftã‚’ç„¡æ–™ã§è©¦ã™ã“ã¨ãŒã§ãã¾ã™ï¼šCraft Vision Pro

ブログをもã£ã¨èª­ã‚€

ÿÿÿÿ