【Swift UI】Identifiableとは?プロトコルとUUIDの使い方

この記事からわかること

  • SwiftIdentifiableとは?
  • Initializer 'init(_:rowContent:)' requires that 'String' conform to 'Identifiable'エラー原因
  • Identifiableプロトコルとは?

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

配列を元にList{}を使ってリストを作成する時にエラーが発生し、「Identifiable」という言葉が出てきたのでその意味と原因をまとめていきたいと思います。

List作成時に起きるエラーの原因

Swift UIのList{}を使って配列をリスト表示させようとした場合に以下のようなエラーが発生しました。

エラー

Initializer 'init(_:rowContent:)' requires that 'String' conform to 'Identifiable'
// イニシャライザー'init(_:rowContent :)'では、'String'が'Identizable'に準拠している必要があります

原因のコード

struct ContentView: View {
    let langs = ["HTML", "PHP", "Swift"]

    var body: some View {
        List(langs){ lang in
            Text(lang)
        }
    }
}

List{}はクロージャ内に記述したコンテンツをリスト形式で描画してくれます。記述方法はコンテンツは1つずつ列挙して記述する方法配列などのまとまったデータの中から1つずつループして取り出す方法などがあります。

そもそもList(配列)と言う記述形式を取りたい場合はIdentifiableプロトコルに準じた構造でないと取り出せないようです。

そのため上記(後者として記述したつもり)の方法では配列の要素を一意に識別できるキー値がないため、配列の値を取り出すことができないようです。

なので配列に識別子となるidを振ることで解決することができます。

Identifiableプロトコルとは?

Identifiableプロトコルとはidプロパティを必須とするプロトコルです。

プロトコルとはクラスや構造体などを定義する際の規約や規格を定義しているルールのようなものです。Swiftでは予め色々な種類のプロトコルが定義されており、その中に「Identifiableプロトコル」が存在します。ちなみにIdentifiableとは「識別可能」という意味の英単語です 。

Identifiableプロトコルの定義

public protocol Identifiable {

/// A type representing the stable identity of the entity associated with `self`.
associatedtype ID : Hashable

/// The stable identity of the entity associated with `self`.
var id: Self.ID { get }
}

定義元を見ると必須のプロパティとしてidが定義されています。

ポイント

配列をプロトコルに準ずるために

配列の中に定義する要素を構造体として保持することでプロトコルに準じたデータにしていきます。まずは構造体を定義します。

struct Lang: Identifiable {
    var id: String
    var name: String
}

配列の各要素を構造体Langに準拠する形で定義します。

struct ContentView: View {
  let langs = [
    Lang(id: "1" ,name: "HTML"),
    Lang(id: "2" ,name: "PHP"),
    Lang(id: "3" ,name: "Swift")
  ]

  var body: some View {
    List(langs){ lang in
      Text(lang.name)
    }
  } 
}

この方法だとidを手打ちで定義しないといけません。これを解決してくれるのがUUIDです。

UUIDとは?

UUID(Universally Unique IDentifier)とはSwift独自のものではなく、識別子の標準規格です。Swiftでは128bit(=16byte)の数値として表されデータ型はUUID型になります。文字列として取得(表示)したい場合はUUID型オブジェクトの uuidStringプロパティを使うとString型の値として取得できます。その際は16進数表記になります。

使用するにはFoundationフレームワークの読み込みが必要になります。

import Foundation

struct Lang: Identifiable {
  var id = UUID()
  var name: String
}

let langs = [
    Lang(name: "HTML"),
    Lang(name: "PHP"),
    Lang(name: "Swift")
  ]
print(langs[0].id) // 8ABE0F22-0EEF-478E-A709-3F271B932AFE
dump(type(of: langs[0].id)) // Foundation.UUID.Type
dump(type(of: langs[0].id.uuidString)) // String.Type

一意でなければいけないidプロパティは初期値にUUID()構造体を使うと自動で一意となるidを割り振ってくれます。

import Foundation

struct Lang: Identifiable {
  var id = UUID()
  var name: String
}

あとは配列の中のデータ構造体に則った形で整形し配列としてまとめてListに渡せば完了です。UUID構造体を初期値にしている場合、明示的なidプロパティへの値の格納は不要になります。

struct ContentView: View {
  let langs = [
    Lang(name: "HTML"),
    Lang(name: "PHP"),
    Lang(name: "Swift")
  ]

  var body: some View {
    List(langs){ lang in
      Text(lang.name)
    }
  } 
}

構造体を使わずに配列を取り出す

配列にわざわざidを振らなくともListの記述形式を変更すれば取り出すことも可能です。

struct ContentView: View {

    let langs = ["HTML", "PHP", "Swift"]

    var body: some View {
        List(langs.indices, id:\.self){ index in
          Text(langs[index])
        }
    }
}

配列.indices「0..<配列の要素数」のレンジを取得できます。indexに格納されるのは0〜配列の要素数までの数なので配列[index]としてindex番目の要素を取り出す点に注意してください。

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index