structとは?-SwiftUIを理解する

Swift

SwiftUIはstruct中心のコードになっています。なのでSwiftUIにおいてstructの理解は非常に重要です。SwiftUIを理解するためにstructについて学習しましょう。かなり初歩的な内容なので退屈な内容かもしれませんが、よければ読んでみてください。

structとは

structとはstructureの略で、日本語では構造体と言います。データ型の一種で、複数の値を格納することができます。例えば、名前、生年月日といった個人情報を管理したい場合には次のような構造体Personを作り、使用することが考えられます。

struct Person {
    var firstName: String
    var lastName: String
    var birthday: Date
}

プロパティとメソッド

structは変数、定数といったプロパティと、メソッドを持つことができます。例えば上の構造体Personに、フルネームを返すメソッドを持たせてみましょう。

struct Person {
    var firstName: String
    var lastName: String
    var birthday: Date
    
    func fullname() -> String {
        return lastName + firstName
    }
}

これでfullname() を呼ぶことでフルネームを返してくれます。

インスタンス生成

実際に構造体Personを使用する際はインスタンスの生成を行なって使用します。また、インスタンスを生成する際に、structに定義されている変数に値を入れて生成することをイニシャライズと言います。

struct Person {
    var firstName: String
    var lastName: String
    var birthday: Date
    
    func fullname() -> String {
        return lastName + firstName
    }
}

// ここから誕生日の生成
let formatter: DateFormatter = DateFormatter()
formatter.calendar = Calendar(identifier: .gregorian)
formatter.dateFormat = "yyyy/MM/dd"
var birthday = formatter.date(from: "2001/06/04")!
// ここまで誕生日の生成

var person = Person(firstName: "Takehusa", lastName: "Kubo", birthday: birthday)

途中にややこしいDate型の誕生日の生成が入ってしまいましたが、こんな感じでインスタンスを生成するときに値を引数で渡すことでイニシャライズできます。

イニシャライザー

structでは上記のようなイニシャライズの方法はとは別に、初期化用メソッドとしてinitという関数を用意して使うことができます。例えば先程のイニシャライズ処理、Date型の誕生日データを作成してからイニシャライズしていますが、イニシャライズの度にあのように誕生日のデータを生成していては面倒です。なので、独自のイニシャライザーを用意して、もっと簡単にイニシャライズできるようにしてみましょう。

struct Person {
    var firstName: String
    var lastName: String
    var birthday: Date

    init(firstName: String, lastName: String, birthdayString: String){
        self.firstName = firstName
        self.lastName = lastName
        
        let formatter: DateFormatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .gregorian)
        formatter.dateFormat = "yyyy/MM/dd"
        self.birthday = formatter.date(from: birthdayString)!
    }

    
    func fullname() -> String {
        return lastName + firstName
    }
}

var person = Person(firstName: "Takehusa", lastName: "Kubo", birthdayString: "2001/06/04")

こうすることで、いちいち日付のStringをDateに変換してからイニシャライズする必要がなくなります。このinitという処理がイニシャライザーです。initというキーワードを使うことでプログラム側にイニシャライザーだと認識されます。イニシャライザーは引数を変えれば複数用意することが可能です。

stored property

struct内に定義される変数と定数のことをプロパティと言いましたが、より細分化するとstored property (宣言型プロパティ)とcomputed property(計算型プロパティ)に分けられます。

stored property (宣言型プロパティ)とは、変数や定数として値を保持するためのプロパティを指します。上記の firstName, lastName, birthday がstored propertyにあたります。

また、stored property には willSetdidSet という監視処理を持たせることができます。変数に代入される前後の値を newValue, oldValue という形で利用することができます。

struct Person {
    var firstName: String = "" {
        willSet {
            print(newValue)
        }
        didSet {
            print(oldValue)
        }
    }
    var lastName: String
    var birthday: Date
}

computed property

computed property (計算型プロパティ)とは決まった値を保持しているのではなく、 get節/set節を使って値を生成するプロパティです。get節は単独で定義できますが、set節はget節がないと定義できません。セットされる値は newValue という形で利用することができます。

struct Person {
    var firstName: String
    var lastName: String
    var fullName: String {
        get {
            lastName + firstName
        }
        set {
            print(newValue)
        }
    }
    var birthday: Date
}

また、値の参照だけに使われるような computed property の場合は、set節を省略しても問題ありません。上のフルネームを表すプロパティのようにfirstNameとlastNameがあり、値を代入する必要はない場合は以下のように書けます。

struct Person {
    var firstName: String
    var lastName: String
    var fullName: String {
        get {
            lastName + firstName
        }
    }
    var birthday: Date
}

さらに get節のみの場合は以下のように省略可能です。

struct Person {
    var firstName: String
    var lastName: String
    var fullName: String {
        lastName + firstName
    }
    var birthday: Date
}

かなり初歩的な内容にはなりますが、structについてまとめて見ました。

コメント