73765

[code]

    private var associatedObjectHandle = "hogeHandle"
    
    struct Hoge {}
    
    extension Hoge {
        var foo: Double? {
            get {
                guard let value = objc_getAssociatedObject(self, &associatedObjectHandle) as? Double else {
                    return nil
                }
                return value
            }
            set {
                objc_setAssociatedObject(
                    self,
                    &associatedObjectHandle,
                    newValue,
                    .OBJC_ASSOCIATION_RETAIN
                )
            }
        }
    }
    
[/code]

このように foo プロパティを struct に生やそうとしましたが結果は nil です。

[code]

    var h = Hoge()
    h.foo = 5.0
    print(h.foo)  // nil
    
[/code]

Hogeをstructではなくてclassに変えると `Optional(5.0)` が表示されるのですが、自動生成された struct
にプロパティを生やしたいので、classに変えることができません。


CC BY-SA 4.0
2021-02-02T08:27:10.553
73758
2021-02-02T10:58:34.163
9008
question
swift
structにobjc_setAssociatedObjectとobjc_getAssociatedObjectでプロパティを生やすことはできないのでしょうか？


>
> structにobjc_setAssociatedObjectとobjc_getAssociatedObjectでプロパティを生やすことはできないのでしょうか？

# できません。

Swiftの class で、`objc_setAssociatedObject`で`objc_getAssociatedObject`が使えるのは、

  * Swiftの class の基底クラス(言語仕様上は存在しないことになっている)は、実は`NSObject`を継承している
  * `NSObject`には AssociatedObject を保持するための隠しスロットがある

と言う事実に基づいています。

Swiftの struct
と言うのは、そのような隠しスロットなどは持たず、C言語のstructのように、宣言されたメンバーがヒープなどを使わず直接メモリ上に展開されるので、AssociatedObject
を保持するような場所がそもそもありません。

* * *

Objective-
C側で`id`型として宣言されている引数にSwiftのstructを渡すと、内部的には`NSObject`を継承している謎クラス`__SwiftValue`のインスタンスが作成されるのですが、このようなインスタンスはstructを渡す度に再生成されるので、`objc_setAssociatedObject`でAssociatedObjectを持たせることに成功しても、そのオブジェクトはすぐに捨てられてしまい、次に`objc_getAssociatedObject`が呼ばれるとAssociatedObjectなんて持っていない新しい`__SwiftValue`のインスタンスが作成される、と言うことになります。

そもそも、Swiftの実行時処理がObjective-
C非依存のプラットフォームでは`objc_getAssociatedObject`や`objc_setAssociatedObject`なんかの「Objective-
Cの実行時処理関連関数」は使えないので、たとえ class であっても、それらに依存していると、移植性が損なわれるなんてことになります。


CC BY-SA 4.0
2021-02-02T10:58:34.163
73765
2021-02-02T10:58:34.163
13972
73758
answer