Stored properties cannot be marked potentially unavailable with ‘@available’ の対処方法

ゴール

Swiftにおけるストアドプロパティで @available を指定する

前提条件

  • iOS(macOS, watchOSでも同様)アプリにおいて、deployment targetをiOS 13にしつつ、iOS 14から利用可能なAPIをiOS 14系のユーザのみ使用したい
  • @available を使用することでユーザのデバイスにおけるOS versionによってアプリの処理を変更することができる

@availableのサンプル

// 特定のOS versionのみ利用可能なclassの指定
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
class MyClass {
    // class definition
}

// iOS 13以降のversionで利用可能なstructの指定
@available(iOS 13.0, *)
struct MyStruct {
    // struct definition
}

// メソッドにおけるversion指定
@available(iOS 14, *)
func limitOSVersion() {
}

// 特定のOS versionにおける条件分岐
if #available(iOS 13, *) {
    print("iOS 13以降が実行される")
} else {
    print("iOS 13未満が実行される")
}

guard #available(iOS 13, *) else {
    print("iOS 13未満が実行される")
    return
}

print("iOS 13以降が実行される")
詳細は下記を参照 https://docs.swift.org/swift-book/ReferenceManual/Attributes.html

問題点

プロパティにおいても下記のように@availableを設定すると、下記コンパイルエラーが発生する
Stored properties cannot be marked potentially unavailable with '@available'
@available(iOS 14.0, *)
struct Fuga {
  let aaa: String
}

struct Hoge {
  @available(iOS 14, *)
  let fuga: Fuga // Stored properties cannot be marked potentially unavailable with '@available' 
}

解決方法

  1. lazy varで指定する
  2. version要求のないprotocolで宣言して、動的にversion要求のある対象を設定する

1. lazy varで指定する

struct Hoge {
  @available(iOS 14.0, *)
  lazy var fuga = Fuga(aaa: "test")
}

2. version要求のないprotocolで宣言して、動的にversion要求のある対象を設定する

protocol NonRequiredVersion {}

@available(iOS 14.0, *)
struct Fuga: NonRequiredVersion {
  let aaa: String
}

struct Hoge {
  let fuga: NonRequiredVersion?

  init() {
    if #available(iOS 13, *) {
      fuga = Fuga(aaa: "test")
    } else {}
  }
}
参考になれば幸いです
最新情報をチェックしよう!