66277


Currency Converter
Bindingsを[vivacocoaのテキスト](http://vivacocoa.jp/swift/swift29.html)に従って作っています。StoryBoard上で3つあるテキストフィールドのうち、3番目をbindすると、ブランクウインドウが表示され、3つのbindすべてを解除するとビューは正しく表示されます。その後、1番目、2番目とバインドしても平気で、やはり3番目をバインドするとブランクに戻ります。

3番目をバインドすると、Xcodeのログには、次のメッセージが出ます。

1.デフォルトの状態

[code]

    2020-05-04 14:57:55.235244+0900 Currency Converter Bindings[33248:1667757] Failed to set (contentViewController) user defined inspected property on (NSWindow): [<Currency_Converter_Bindings.Converter 0x6000002549c0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key amountInOtherCurrency.
    
[/code]

2.スキームの引数に-NSBindingDebugLogLevel 1をセットした場合

[code]

    2020-05-04 13:43:07.679365+0900 Currency Converter Bindings[32504:1618056] Cocoa Bindings: Error accessing value for key path selection.amountInOtherCurrency of object <NSObjectController: 0x600003304aa0>[object class: NSMutableDictionary] (from bound object <NSTextField: 0x1004118e0>): [<Currency_Converter_Bindings.Converter 0x60000020a160> valueForUndefinedKey:]: this class is not key value coding-compliant for the key amountInOtherCurrency.
    
[/code]

モデルとなるConverterクラスのコード

[code]

    import Cocoa
    
    class Converter: NSObject {
    
        @objc dynamic var exchangeRate:Double = 0.0
        @objc dynamic var dollarsToConvert:Double = 0.0
    
        func amountInOtherCurrency() ->Double {
            return self.exchangeRate * self.dollarsToConvert
        }
    
        override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> {
            if key == "amountInOtherCurrency" {
                return Set<String>(arrayLiteral: "exchangeRate", "dollarsToConvert")
            } else {
                return super.keyPathsForValuesAffectingValue(forKey: key)
            }
        }
    }
    
[/code]

体系的な理解ができていないため、色々いじりましたが、何故うまく動作しないのか分かりません。どうか皆さんのお知恵をお貸しください。ちなみに同じUIパーツでObjecctive-
Cで作ったものは動きました。


CC BY-SA 4.0
2020-05-04T07:02:28.283
66275
2020-05-04T07:40:02.950
2020-05-04T07:24:25.880
13972
516
question
swift macos
Currency Converter BindingsでamountInOtherCurrencyをbindすると、ブランクウインドウが表示される


macOSのBindingの仕組みはObjective-Cの動的な機構に基づいているため、若干のObjective-Cに関する知識が必要です。

残念ながら、リンク先の記事の時代とはObjective-
C関連の動作が変わってしまったので、もし古い記事を参考にするのであれば、そこら辺は自分で調べて修正してやらないといけません。

で、BindingのModel Key Pathに`amountInOtherCurrency`と入力するのであれば、Objective-
C側から`amountInOtherCurrency`と言うメソッドが見えていないといけません。

記事に書いてあるコードに対して、2つのプロパティと同じように、Swiftの`amountInOtherCurrency()`メソッドにも`@objc`をつけてやらないとObjective-
C側からは見えません。

[code]

        @objc func amountInOtherCurrency() -> Double {
            return exchangeRate * dollarsToConvert
        }
    
[/code]

(Model→Viewへの一方向Bindingでは、dynamicはなくても動くんですが、つけても構いません。)

あるいは、他の2つに合わせるなら、計算型プロパティに変更しても構いません。

[code]

        @objc var amountInOtherCurrency: Double {
            exchangeRate * dollarsToConvert
        }
    
[/code]

* * *

エラーメッセージにある、「this class is not key value coding-compliant for the key
amountInOtherCurrency」と言うのは、「`amountInOtherCurrency`と言うキーについて、KVCに準拠していない」と言う意味ですが、言い換えると「`amountInOtherCurrency`に対応するgetter(場合によってはsetter)メソッドが存在しないか、Objective-
C側から見えない」と言うことになります。

メッセージの意味を理解して正しく対応できるようにしてください。


CC BY-SA 4.0
2020-05-04T07:40:02.950
66277
2020-05-04T07:40:02.950
13972
66275
answer