Skip to content

Version 4 の最新情報

RedRimmedBox edited this page Oct 31, 2023 · 16 revisions

ついに Version 4.0.0 リリースしました!! Wiki の更新は随時行ってまいります. また, SKNodeBuilder は Documentation catalog に簡単なガイドを載せておりますので, そちらも是非ご参考に.

新しい Builder の構造

現在開発中の Builder の構造を図示しました.

Builder 001
  • Builder は Generator と Processor を保持します.
  • Processor は入れ子構造になっており, それぞれが Modifier を保持します.
  • 図ではLinkとなっていますが, これも Processor の一種です.

ノードインスタンスが生成される流れ(あくまでイメージです)

  1. GeneratorSKNode のインスタンスを生成します.
  2. 生成されたインスタンスは Processor の入れ子の最奥部まで移動します.
  3. インスタンスが Processor の最奥から外へ向かって移動し, その際に Modifier がインスタンスを編集します.

Linked modifier

モディファイアを追加すると, ビルダーの型が変化します.

Modifier changes the type of the builder.

linked-modifier-sample-code

What's new?

何が良くなった?

Version 3 との大きな違いは, ビルダーがノードのインスタンスを保持しないことです. Version 4 では, 上の写真でコメントアウトされている, node() メソッドを実行して, 初めてノードのインスタンスが作られます. ビルダーがノードを保持しないことで得られるメリットは以下の通りです.

  • ビルダーオブジェクトが value semantics を持つことができる(ただし, modifier の実装による).
  • ビルダーオブジェクトが参照を持たないため, メモリーリークをすることがなくなる(ただし, modifier の実装による).

What is a modifier that destroys the value semantics of a builder?

ビルダーの value semantics を破壊する modifier とは?

先ほどの説明ではこんなことが書いてありました.

(ただし, modifier の実装による)

いったいどんな modifier を作ったら value semantics を破壊するのでしょう? 結論から言うと, 参照型のインスタンスを使用する modifier が, モディファイアをセットした Builder 全体の value semantics を破壊します.

例えば, あなたがカスタムモディファイアとして以下のような参照を持つモディファイアを作ったとします.

struct YourMod<T: SKNode>: Modifier {
    var anotherNode: SKNode // ここが参照!

    func mod(node: T) {
        node.addChild(self.node)
    }
}

このモディファイアをビルダーにセットすると, そのビルダーは value semantics が破壊され, かつ循環参照を作ることができる(この時点では循環参照になりません)ようになるため, メモリリークの危険もどこかで現れるかもしれません.

  • tips: この場合, せめて weak varunowned let を使うといいかもしれません. 循環参照だけでも回避できますので.

以下は悪影響の例です.

// 参照を持つモディファイアが Builder の value semantics を破壊する様子.
// 変数 builder_0 が 変数 builder_1 に影響を及ぼしている.

let node = SKNode()
let modifier = YourMod<SKNode>(anotherNode: node)

let builder_0 = Builder()
    .modifier(modifier)

let builder_1 = Builder()
    .modifier(modifier)

let node_0 = builder_0.node()

let node_1 = builder_1.node() // error! 同一のノードを別々のノードに接続してしまった!

Custom modifier

Modifier プロトコルを使用してモディファイアを作成できます.

struct YourMod: Modifier {
    func mod(node: SKLabelNode) {
        node.text = "My modifier!!"
        node.fontColor = .red
    }
}

let builder = Builder<SKLabelNode>()
    .modifier(YourMod())

Processor

定義済みのノードを編集する意図でビルダーを使えるようになりました.

Generator

ついにノードの初期化を実現しました!

ノードの初期化を実現したオブジェクトは, Generator と名付けられました.

Generator は Processor とともに Builder に装備され, これにより Builder はさまざまなイニシャライザでノードを初期化することができるようになりました.

Generator の生成は, Generators<Node>.make() メソッドで作成できます.

しかし新たな欠点が生まれました。それは、生成に必要なコードが長くなってしまったことです。version 5 に向け、現在のメモリ管理システムをなるべく維持しながら、コード量を短くできる方法を模索しています。