View in English

  • メニューを開く メニューを閉じる
  • Apple Developer
検索
検索を終了
  • Apple Developer
  • ニュース
  • 見つける
  • デザイン
  • 開発
  • 配信
  • サポート
  • アカウント
次の内容に検索結果を絞り込む

クイックリンク

5 クイックリンク

ビデオ

メニューを開く メニューを閉じる
  • コレクション
  • トピック
  • すべてのビデオ
  • 利用方法

WWDC24に戻る

ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。

  • 概要
  • トランスクリプト
  • コード
  • Embedded Swiftでサイズを縮小

    Embedded Swiftを使用すると、制限の厳しい環境において、より安全かつ表現力に富む方法でSwiftによる開発を行えます。このセッションでは、既製のMatterデバイスでのデモを交えて、さまざまなマイクロコントローラ上でEmbedded Swiftを実行する方法を解説します。Swiftのさまざまなメリットをランタイムなしの小さなフットプリントで提供するEmbedded Swiftのサブセットの仕組みと、Embedded Swiftの利用を始めるうえで役立つ幅広いリソースもご紹介します。

    関連する章

    • 0:00 - Introduction
    • 0:25 - Agenda
    • 0:46 - Why Embedded Swift
    • 2:30 - Showcase
    • 2:47 - The plan
    • 3:39 - Getting started
    • 6:19 - Using Swift's interoperability to control the LED
    • 7:12 - Using an ergonomic LED struct
    • 10:07 - Adding the Matter protocol
    • 13:43 - Using a Swift enum in the event handler
    • 16:52 - Demo summary
    • 17:34 - How Embedded Swift differs
    • 19:48 - Explore more
    • 21:32 - Wrap up

    リソース

    • A Vision for Embedded Swift
    • Embedded Swift User Manual
    • Forum: Programming Languages
    • Swift Embedded Example Projects
    • Swift Forums Embedded Discussion
    • Swift Matter Examples
    • Swift MMIO
    • Tools used: Neovim
      • HDビデオ
      • SDビデオ

    関連ビデオ

    WWDC21

    • スマートホームAppへのMatterのサポートの追加
  • このビデオを検索

    ようこそ Kuba Mracekです ご存じのとおり Swiftは Appleプラットフォームと他の環境の アプリ開発に効果を発揮する 強力な言語です 今日はそんなSwiftを 新しく エキサイティングで コンパクトな 組み込みデバイスで 活用する話をします 最初に Embedded Swiftを紹介し その後にデモをお見せして 実用的なアプリの作り方を説明します Embedded Swiftを使った アプリ開発のやり方と デスクトップやモバイルの Swiftとの違いを説明し 最後に 詳しい情報を得たい方のために リソースを紹介します では始めましょう 皆さんが現在お使いのSwiftは さまざまなソフト開発に対応し モバイルデバイス デスクトップや サーバを対象にできます

    このセッションでは Swiftが 新たに進出したエリアである 組み込みデバイスについてお話しします 誰もが日常的に使っている スマートライト サーモスタット アラーム スマートファン 音楽デバイス LEDテープライト その他 多くの身近なガジェットには プログラマブルなマイクロ コントローラが組み込まれています 今日は 趣味のプログラマーと 本格的なデベロッパの両方に向けて Swiftによる組み込みデバイス向け 開発のやり方を説明します その手段として新たに登場した Embedded Swiftは 制約が大きい組み込みデバイスに特化した 新しいコンパイルモードです 従来 この世界ではCとC++が 標準的な開発言語として使われてきました 今後はそこにSwiftが加わります 組み込み開発に携わる皆さんに Swiftの長所である 人間工学的なデザインや 安全機能 使いやすさをもたらします

    Embedded Swiftは 組み込みデバイスの マイクロコントローラ向け プログラミングだけでなく カーネルレベルや その他の低レベルライブラリコードなど 新たな依存関係を持ち込むことが 難しい用途にも適しています Appleデバイス上の動作環境は Secure Enclaveプロセッサであり Swiftのメモリが備える 安全性は大きなメリットです Embedded Swiftはサブセットですが 愛用されているSwiftの言語仕様を ほぼ網羅した フル機能のサブセットです 値型と参照型をはじめ クロージャやオプショナル型 エラー処理 ジェネリックスなども サポートされています では Embedded Swiftの ライブデモに移りましょう

    ところで Embedded Swiftの機能は 今はまだ実験段階です ソースの安定段階には 至っていません 活発な開発作業の最中ですから 現時点では swift.orgの previewツールチェーンでの 利用をおすすめします

    このデモでは HomeKitアクセサリの 非常にシンプルなプロトタイプとして カラーLEDライトを作ります まず HomeKitの動作環境を セットアップします つまり WiFiネットワークや 既にあるAppleデバイスの接続を 確立しておきます ここでは プログラマブルな 組み込みデバイスとして ESP32C6開発ボードを使うことにします RISC-Vマイクロコントローラ 搭載のボードに カラーLEDが1個 装備されています このデバイスを USBケーブルでMacに接続して HomeKitアクセサリを 実装するプログラムを Embedded Swiftで作成してから デバイスに書き込みます すると このデバイスが WiFi環境と HomeKitネットワークに接続され どのAppleデバイスからも ホームアプリを使って 制御できるようになります

    始めましょう これはNeovimとCMakeです いま見ているテンプレートプロジェクトは 非常に基本的な内容で Embedded Swiftコードを 実行するだけのものです プロジェクトで使っているSDKは デバイスベンダーから提供されたもので C言語で書かれています そのベンダー製SDKを 無変更で使えるよう ブリッジヘッダーを利用し SDKのすべてのAPIを Swiftにインポートしています

    ベンダー製のSDKとビルドシステムの上で Swiftのコードをビルドするには 簡単なCMakeロジックが必要です

    そのために 追加のファイルとして 定型的なYAMLファイルや

    CSVファイル

    sdkconfigファイルを用意します

    このSDKをプロジェクトで使うために 必要なファイルだったので ベンダーから提供された サンプルを参考にしてセットアップし その上にSwiftを追加しました

    Swiftのソースコードに戻りましょう このエディタにはLSP連携機能があり 使おうとしている関数や型の 定義とドキュメントを 見ることができます

    セマンティック自動補完機能も 充実しています

    意味をなさないコードを 書こうとすると

    すぐに エラーメッセージと 問題点を示す警告文が表示されます デバイスをケーブルで接続しましょう

    USB経由で デバイスに プログラムを書き込みます ブレッドボードに バッテリーを付けてあるので 書き込みが完了した後は USBを抜いても デバイスを動かし続けることができます しかし まずは このデバイス上で 最も簡単なSwiftアプリが 動くことを確かめましょう このSDKには 確認用ツールが用意されています

    ベンダーから提供された 便利な Pythonスクリプトを実行してみましょう デバイスのビルド 書き込み 監視を すべて1つのコマンドで行えるものです

    実行すると ファームウェアのビルド進行状況と デバイスへのアップロード状況 デバイスから受信したログが表示されました 続いて 初めて作った Embedded Swiftアプリが 組み込みデバイス上で動いていることを 示すサインが表示されました 次は もっと有用なコードを 追加してみます Swiftには優れた相互運用性があり ベンダーSDKの すべてのAPIにアクセス可能です デバイス上のLEDを 制御するときは Cで書かれた SDKの従来のAPIが使えます

    それらのAPIを呼び出して 制御してみましょう "青色" "彩度100%" "明るさ80%" の値を送ることにします

    このバージョンのコードを保存し デバイスにアップロードします

    先ほどと同じコマンドを実行します

    ファームウェアのアップロードが 数秒で完了し デバイスが再起動すると LEDの色や明るさを 制御できるようになりました

    しかし 何か操作をするたびに SwiftからC APIを呼び出すのは面倒です それができること自体は有意義ですが ラッパーを作り C APIを抽象化して扱えるようにすれば アプリ開発時に クリーンかつ直感的で 人間工学的なSwiftコードを書けます そのバージョンのために作った LEDオブジェクトの定義を見てみましょう

    これは 私が作っておいた ヘルパーコードです わかりやすいSwiftレイヤーで C APIをラップしており 有用かつ人間工学的な 型のプロパティを持っています たとえば enabledプロパティはブール型 brightnessプロパティは整数型です メインのアプリロジックを 含んだファイルに戻りましょう LEDオブジェクトを使うと とても明快で直感的なコードを書けます

    起動時は赤色で光らせるようにしましょう

    明るさは80%にします

    非常に読みやすく 明快なコードでしょう

    コーディングを続けます

    ループを追加して 1秒経つごとに LEDの状態を反転させます また オンにするときは どういう新しい色で光らせるか 色相と彩度の値が 変化できるようにします 色相はランダムに決めて 彩度は100%にしましょう このように Embedded Swiftのコードは 普通のSwiftに近い感覚で作成でき ほとんどの言語要素を同じように使えます もう一度ファームウェアを アップロードします

    うまく動くか見てみましょう 起動して実行が始まると デバイスのLEDの色が ランダムに切り替わります

    すばらしい! まさに期待どおりの結果です LEDオブジェクトのレイヤーを 作ったことで Swiftの本領が発揮され 高レベルのAPIにより クリーンで読みやすいコードになりました

    ご覧のとおり Embedded Swiftは 皆さんのワークフローによく馴染みます ベンダーから提供されたSDKを使えますし お使いのIDEやテキストエディタで 完全な自動補完機能を利用でき 定義やドキュメントも参照できます Swiftの優れた相互運用機能によって 従来のSDKに含まれるC APIも Swiftコードから直接呼び出せます とはいえ多くの場合 C APIは コアアプリロジックから切り離し 人間工学的で直感的なAPIレイヤー内に ラップして利用するのがおすすめです

    基本的な動きを確認できたので 実際のHomeKitアクセサリを 作っていきましょう これには Matterプロトコルを使います Matterはスマートホームアクセサリ 向けのオープンな標準です 2021年のWWDCセッションで 詳しく取り上げられたので 詳細を知りたい方は ぜひそちらをご覧ください

    私が使っているSDKでは C++ API の形でMatterを利用できるため Swiftの相互運用機能を使って 呼び出すことで インフラストラクチャのデバイス検出や コミッショニングなどの機能を すべて無料で活用できます

    また Matterプロトコル対応デバイスは 新しく入手したときから Matterアクセサリに ネイティブ対応しているため 自動的にHomeKitの中で 機能を発揮します もう一度 何もしない空のアプリを 作るところから始めましょう Matterを扱うには データモデルと用語を 少し知っておく必要があります Matterデバイスを実装する際に 必要となる作業の 大まかなリストをご覧ください まず ルートノードというものを作ります これは そのMatterアクセサリ 自体を表します 次に エンドポイントを作る必要があります エンドポイントは 状態を持ったオブジェクトで この例では カラーLEDライトが該当し 状態は色や明るさなどを表します また ライトのオン/オフなど コマンドを受け付けることができます

    そのエンドポイントをノードに接続し さらに ノードを applicationオブジェクトに接続します 私があらかじめ作っておいた シンプルな C++ Matter APIラッパーレイヤーが Matterサブディレクトリに 入っています

    これは 使いやすいAPIと同じ考え方で 作った Matter API用のレイヤーで LEDライトを制御できます それがあると 最上位ロジックを組むのが簡単になります

    最初は ルートノードの作成

    次は エンドポイントの作成と構成

    エンドポイントはカラーLEDライトで eventHandlerのクロージャは HomeKitからエンドポイントに イベントが届くたびにトリガーされます コールバックの実装には クロージャが適しています Cのコールバックでよく使われるような 安全でない関数ポインタや 型指定なしのコンテキスト引数は扱いません その次は エンドポイントの登録 最後に Matterアプリの セットアップと起動です

    まだ 全イベントの文字出力しか ロジックはありませんが 有効なMatterアプリを 1つ作ることができました このアプリを デバイスに書き込みましょう

    起動までは少し時間がかかります 普通 この後は新しいアクセサリの セットアップを実行しますが 今日の環境では実行済みです また HomeKitネットワークへの デバイス登録も済ませたので 参加先のWiFiネットワークも 設定済みです ネットワークに接続すると Macやその他デバイスのホームアプリに すぐに"Matter Accessory" として表示されます

    スマートライトとして認識され Macのホームアプリから 制御できるようになりました ここでライトのオン/オフ操作をすると デバイスがイベントを受信して 制御コマンドを受け取り デバイスログを出力します

    今は 届いたイベントを ログに出力しているだけですが 次は 意味があるコードを実装し LEDオブジェクトを使って 先ほど見たような制御を 実行させましょう イベントハンドラでは 場合によって 異なる属性を設定できる必要があります 属性はSwiftの列挙型なので switchステートメントが使えます

    どのようなケースを含めるべきかは 自動補完でわかります

    各種の属性に対応するコードを 記述しましょう 受信したイベントに基づいて enabledプロパティを設定することで ライトのオン/オフを 切り替えることができます また 明るさのプロパティを設定するときは 値の範囲を適切に調整します 同じように 色の変化を処理する場合も 色相や彩度 色温度の 新しい値を設定します コーディングが済んだので デバイスにこのプログラムを 書き込んでテストしましょう

    起動するまでお話を Swiftの列挙型は 人間工学的に優れた便利なしくみです

    列挙型は 非常に単純なケースでは 集合に含まれる1つの選択肢を表します この例では 属性.onOffや .levelControlが該当します

    関連する値が付随することもあります たとえば .colorControlは ペイロードを伴っています Swiftのパターンマッチ機能のおかげで switchステートメントを ネストさせる必要はありません このように ペイロードを添えた ケースを書けば済みます

    同じく colorプロパティも 列挙型で表現されていて

    色相+彩度 または色温度の 2とおりの形式を使用できます

    これらのケースでは ペイロードの型も違っています 一方のケースでは ペイロードは2つの整数

    もう一方のケースは整数1つだけです この使い方ができる Swiftの列挙型は とても強力で表現力があり シンプルに 簡潔に 読みやすく ロジックを記述できます

    さて デバイスが起動しました バッテリーの電力で動くので USBケーブルは抜くことができます

    デバイスの制御は ホームアプリからワイヤレスで行えます ライトをつけてみます

    消します

    明るさを調整してみます

    色温度を切り替えてみます

    自由に色を指定することもできます いくつかの色を試してみましょう

    いいですね スマートライトの試作品が うまく動いています こうして Embedded Swiftを使い HomeKit対応スマートライトを 開発できました 実際にやってみたい方は GitHubに デモプロジェクトと セットアップ手順があります

    このように Swiftでは 相互運用機能を生かし HomeKit対応デバイスの 基本的なプロトタイプを ごく短時間で作り 動作させることができます Matterプロトコル全体を Swiftで実装し直す必要はなく 既にある実装を Swiftから利用できます Swiftは コードの設計と実装を クリーンで直感的なものにし 読みやすさと安全性を CやC++よりも向上させることができます 先ほども クロージャを使ってコールバックを書き 人間工学的なコードで実装できました Embedded Swiftは 普通のSwiftに近い感覚で使うことができ デモで見たとおり ほぼ同じ言語機能を備えていますが 異なる点もあります

    組み込み環境には いずれも非常に厳しい制約があり 小さくてシンプルなプログラムの バイナリしか搭載できません メモリとストレージのサイズや CPUの性能も非常に限られています その要件に合わせるため 一部の機能は Embedded Swiftでは 無効になっています たとえば 実行時リフレクションについて 考えてみましょう ある型の子について検査するには 型のメタデータレコードを 参照する必要があります それには フィールドの名前や オフセットと型情報が含まれ さらに他のメタデータレコードへの 参照なども発生します そうしたレコードの扱いは 組み込みデバイスの規模を超えた コードサイズコストになります

    このため Mirror APIによる 実行時リフレクションは 完全なSwift環境でしか利用できません Embedded Swiftでは無効です 同じ理由で メタデータの参照を 実行時に発生させないよう メタタイプと"any"型も 無効になっています しかし 心配は無用 ごくわずかな範囲を除き そのままの言語機能が備わっています

    Embedded Swiftは Swiftの フル仕様を厳守したサブセットで 変種や方言のようなクセはありません Embedded Swiftの挙動は 完全なSwiftと同じです そこに違いはありません Embedded Swiftで使える すべてのコードは 完全なSwiftでも動作します

    使おうとした機能が Embedded Swiftにない場合は コンパイラが教えてくれます たとえば any型を使おうとすると このようになります

    このエラーは any Countableを ジェネリクスに置き換えれば 回避することができます このコードスニペットは any Countableを some Countableに書き換えたものです この変更で 関数は ジェネリック関数になりました ジェネリック関数は コンパイラによって特定されるので Embedded Swiftでも 完全にサポートされています このコーディングにすると コストが大きい実行時サポートや 型メタデータは必要ありません Embedded Swiftには 他にも興味深い点が山ほどあります Swift Evolutionプロセスにおいても Embedded Swiftのビジョン ドキュメントが公開/承認されました そのドキュメントでは Embedded Swiftの 概要設計 要件 アプローチが 説明されており コンパイルモードや言語サブセットの 知識を得る資料として最適です Embedded Swiftを試してみたい方は 「Embedded Swift -- User Manual」 をぜひ読みください 使い始める方法や できること できないことがわかりますし ベンダー製の SDKやビルドシステムの扱いに関して 知っておく必要がある情報も 得られます たとえば コンパイラに指定するフラグや 満たす必要がある 依存関係などがわかります

    GitHubには 私たちがEmbedded Swiftで作った サンプルプロジェクト群があります ARMまたはRISC-Vマイクロ コントローラ搭載の 組み込みデバイス各種を 扱った内容で 広く使われている 人気の組み込み開発ボードや ゲーム端末Playdateなど いろいろなデバイスが含まれます サンプルは 各種ビルドシステムや 統合オプションの使い方を理解し Embedded Swiftの利用価値を知る 情報源になるだけでなく アイデアを練るための テンプレートとしても役立ちます 埋め込みデバイス上で 実行するコードでは 低レベルのハードウェアレジスタ操作が よく行われるので そうした用途向けの Swift MMIOライブラリを公開しました これは メモリマップドレジスタの操作を 安全に 体系的に 人間工学的に行える APIを提供するものです 最後に Swift Forumsに 新たなサブカテゴリ "Embedded"が設けられました 皆さんが 新しい試みや 質問 議論の やり取りなどを行う場として最適です

    以上 組み込みデバイス用の 新しいコンパイルモード Embedded Swiftの使い方を 紹介してきました 今はプレビュー公開の段階であり swift.org nightlyツールチェーン での利用が前提になります 32ビットと64ビットの ARMチップ RISC-Vチップが 現時点で両方サポートされています なお Embedded Swift自体は 特定のハードウェアに依存しないため 新しい命令セットへの対応は簡単です Embedded Swiftで ぜひ魅力的な プロジェクトを作ってみてください 体験談やご意見を Swift Forumsでお待ちしています ありがとうございました WWDCをお楽しみください

    • 3:50 - Empty Embedded Swift application

      @_cdecl("app_main")
      func app_main() {
        print("🏎️   Hello, Embedded Swift!")
      }
    • 6:48 - Turning on LED to blue color

      @_cdecl("app_main")
      func app_main() {
        print("🏎️   Hello, Embedded Swift!")
        var config = led_driver_get_config()
        let handle = led_driver_init(&config)
        led_driver_set_hue(handle, 240) // blue
        led_driver_set_saturation(handle, 100) // 100%
        led_driver_set_brightness(handle, 80) // 80%
        led_driver_set_power(handle, true)  
      }
    • 8:32 - Using an LED object

      let led = LED()
      
      @_cdecl("app_main")
      func app_main() {
        print("🏎️   Hello, Embedded Swift!")
      
        led.color = .red
        led.brightness = 80
      
        while true {
          sleep(1)
          led.enabled = !led.enabled
          if led.enabled {
            led.color = .hueSaturation(Int.random(in: 0 ..< 360), 100)
          }
        }
      }
    • 12:44 - Matter application controlling an LED light

      let led = LED()
      
      @_cdecl("app_main")
      func app_main() {
        print("🏎️   Hello, Embedded Swift!")
        
        // (1) create a Matter root node
        let rootNode = Matter.Node()
        rootNode.identifyHandler = {
          print("identify")
        }
        
        // (2) create a "light" endpoint, configure it
        let lightEndpoint = Matter.ExtendedColorLight(node: rootNode)
        lightEndpoint.configuration = .default
        lightEndpoint.eventHandler = { event in
          print("lightEndpoint.eventHandler:")
          print(event.attribute)
          print(event.value)
      
          switch event.attribute {
          case .onOff:
            led.enabled = (event.value == 1)
          
          case .levelControl:
            led.brightness = Int(Float(event.value) / 255.0 * 100.0)
          
          case .colorControl(.currentHue):
            let newHue = Int(Float(event.value) / 255.0 * 360.0)
            led.color = .hueSaturation(newHue, led.color.saturation)
          
          case .colorControl(.currentSaturation):
            let newSaturation = Int(Float(event.value) / 255.0 * 100.0)
            led.color = .hueSaturation(led.color.hue, newSaturation)
          
          case .colorControl(.colorTemperatureMireds):
            let kelvins = 1_000_000 / event.value
            led.color = .temperature(kelvins)
          
          default:
            break
          }
        }
        
        // (3) add the endpoint to the node
        rootNode.addEndpoint(lightEndpoint)
        
        // (4) provide the node to a Matter application, start the application
        let app = Matter.Application()
        app.eventHandler = { event in
          print(event.type)
        }
        app.rootNode = rootNode
        app.start()
        
      }
    • 18:03 - Reflection example

      // Reflection needs metadata records
      
      let mirror = Mirror(reflecting: s)
      mirror.children.forEach { … }
      
      struct MyStruct {
        var count: Int
        var name: String
      }
    • 18:57 - Unavailable features will produce errors

      // Unavailable features will produce errors
      
      protocol Countable {
        var count: Int { get }
      }
      
      func count(countable: any Countable) {
        print(countable.count)
      }
    • 19:24 - Prefer generics over “any” types

      // Prefer generics over “any” types
      
      protocol Countable {
        var count: Int { get }
      }
      
      func count(countable: some Countable) {
        print(countable.count)
      }

Developer Footer

  • ビデオ
  • WWDC24
  • Embedded Swiftでサイズを縮小
  • メニューを開く メニューを閉じる
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    メニューを開く メニューを閉じる
    • アクセシビリティ
    • アクセサリ
    • App Extension
    • App Store
    • オーディオとビデオ(英語)
    • 拡張現実
    • デザイン
    • 配信
    • 教育
    • フォント(英語)
    • ゲーム
    • ヘルスケアとフィットネス
    • アプリ内課金
    • ローカリゼーション
    • マップと位置情報
    • 機械学習
    • オープンソース(英語)
    • セキュリティ
    • SafariとWeb(英語)
    メニューを開く メニューを閉じる
    • 英語ドキュメント(完全版)
    • 日本語ドキュメント(一部トピック)
    • チュートリアル
    • ダウンロード(英語)
    • フォーラム(英語)
    • ビデオ
    Open Menu Close Menu
    • サポートドキュメント
    • お問い合わせ
    • バグ報告
    • システム状況(英語)
    メニューを開く メニューを閉じる
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles(英語)
    • フィードバックアシスタント
    メニューを開く メニューを閉じる
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(英語)
    • News Partner Program(英語)
    • Video Partner Program(英語)
    • セキュリティ報奨金プログラム(英語)
    • Security Research Device Program(英語)
    Open Menu Close Menu
    • Appleに相談
    • Apple Developer Center
    • App Store Awards(英語)
    • Apple Design Awards
    • Apple Developer Academy(英語)
    • WWDC
    Apple Developerアプリを入手する
    Copyright © 2025 Apple Inc. All rights reserved.
    利用規約 プライバシーポリシー 契約とガイドライン