[SwiftUI] マルチプラットフォーム 対応しつつ view modifier を適用する

SwiftUI

SwiftUI で使うことができるマルチプラットフォーム対応の View Modifier の作り方を説明します。

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Big Sur 11.1
  • Xcode 12.3
  • iOS 14.2

マルチプラットフォーム対応の定義

ここでは、以下を指して マルチプラットフォーム対応と書いてます。

  • 同一のコードで、複数プラットフォームをターゲットとした時に コンパイルエラーにならない
  • 特定のプラットフォームにのみ存在する機能を、そのプラットフォーム上で利用できる

特定のプラットフォームにのみ存在する機能を別プラットフォームにも実装していくことは、想定していません。

背景

SwiftUI になって、Apple の複数のプラットフォームへの対応が容易になってきました。

基本的な View は、複数プラットフォーム対応ですし、個別 OS への対応用のコードは、以下のように #if – #endif で囲うことで、対応できます。

もちろん、#else を使って、プラットフォーム毎に機能を実装することもできます。

iOS 向けの専用コード

上記のコードでは、”何らかの処理”の部分は、iOS 向けにのみコンパイル対象となるので、iOS にのみ存在する関数等を使用しても他ターゲットでコンパイルエラーが発生する等もありません。

Swift[Swift] マルチプラットフォームで使えるコードを記述する方法

#if / ViewModifier の問題点

OS の違いは、用意されている API の違いだけではなく、View Modifier の違いもあります。

付与する View Modifier を使い分けるために、#if – #endif を使おうとして以下のようなコードを書くと、問題が発生します。

コンパイルエラー

エラーは、#if – #endif で囲う範囲は、”Statement” である必要があることから来ています。

# ちなみに、#if – #endif を削除すると iOS ターゲットでは問題なく動きます。macOS ターゲットでは、’editMode’ is unavailable in macOS というコンパイルエラーとなります。

View Modifier 内部でのマルチプラットフォーム対応

#if – #endif で囲う範囲が “Statement” であることが必要であれば、そのようにすれば良いということになります。

以下のような ViewModifier を作って、その内部で、#if – #endif を使います。

onlyiOSModifier

先ほどのコードは以下のようになります。

example

こうすることで、macOS ターゲットでもコンパイルエラーとならず、iOS ターゲットでは 指定したかった View Modifier が付与される状態となります。

すこし拡張

一つのビューに、OS 毎に指定したい View Modifier が異なるケースを想定して、少し拡張してみます。

まずは、OS を定義

以下のように OS を定義しました。(システムのどこかに定義されているかも・・・)

define OS

OS を判別して、適切な modifier を適用する

OS を判定して、modifier を起用するようにします。

applyOSModifier

上記では、iOS のみ実装していますが、macOS, tvOS 等も同様です。

使用例は以下のようになります。

使用例

ここまでくると、マルチプラットフォーム対応のコードを書けた気になります。

注意点

当初、closure として外部から modifier を渡すことを検討していました。

しかし、closure で渡すとすると プラットフォーム依存のコードは、その内部でも #if – #endif を使うことになってしまい、コードが複雑化してしまいます。

ここまで実装してみて分かったのは、現時点では 標準的なコードで マルチプラットフォームを実現することは容易ですが、すこしでもその枠からはみ出ると 必要な手間が大幅に増えるということでした。

まとめ:マルチプラットフォーム対応の View Modifier

マルチプラットフォーム対応の View Modifier
  • view modifier には、#if os(XX) – #endif は使えない
  • view modifier を作って、その内部で #if os(XX) – #endif を使う
  • view extension を作ると、modifier 的に使えて便利

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です