問題タブ [cocoa-bindings]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
cocoa - Cocoa での KVO/Bindings 準拠のブリッジ パターンの実装
ブリッジオブジェクトが任意の他の NSObject インスタンスの kvo/bindings 準拠のドロップインとして機能する単純なオブジェクトブリッジをココアに実装しようとしています。
ここに私の問題があります(以下のコードの詳細):
ブリッジ オブジェクトは、name という名前の NSString* プロパティとAddress* プロパティaddressを使用して、Person-Object のドロップインとして機能します。Bridge の keyPath の「名前」または「アドレス」へのバインドはうまく機能します。ブリッジの keyPath "address.street" に何らかのオブジェクトをバインドし、新しい Address-Object が Person のaddressプロパティに設定されると、問題が発生します。その結果、次のような KVO 関連の例外が発生します。
Cannot remove an observer <NSKeyValueObservance 0x126b00> for the key path "street" from <Address 0x12f1d0> because it is not registered as an observer
これは、ブリッジが「address」プロパティの変更を認識し、willChangeValueForKeyPath/didChangeValueForKeyPath タプルを発行した場合でも発生します。
以下のコードは問題を引き起こします。ファイル「BridgeDemo.m」に保存し、コンパイルして実行できる自己完結型の目的の C コードです。
この問題の解決策を知っているか、同じ問題を解決するためのより良いアプローチを提供してくれるなら、私はとても幸せなプログラマーになります!
BridgeDemo.m:
cocoa - 共有ユーティリティウィンドウと最前面のドキュメントウィンドウからバインドするための良い方法は何ですか?
複数のNSDocumentを開くことができるアプリケーションがあります。このアプリケーションには、最前面のドキュメントに適用したいいくつかの機能を含む単一のユーティリティウィンドウがあります。
ここではバインディングを使用しようとしているので、ユーティリティウィンドウのユーザーインターフェイスを最前面のドキュメントにクリーンにバインドする方法がコツです。目標は、最前面のドキュメントウィンドウを切り替えると、ユーティリティウィンドウのビューが更新されることです。最前面のドキュメントのモデルのプロパティにバインドされているコントロールは、ドキュメントのモデルなどで状態が変化したときに適切に更新されます。
このようなウィンドウからアクションを送信する場合は、ファーストレスポンダーを使用するだけで簡単です。ドキュメントオブジェクトは、レスポンダーチェーンを介してアクションをインターセプトできます。しかし、私はこれ以上のものが欲しいです、そしてもちろんあなたはファーストレスポンダーに拘束することはできません。
私が持っているいくつかのアイデア:
- 共有ウィンドウのペン先にオブジェクトコントローラーを配置します。ドキュメントウィンドウの最前面のステータスが変更されたら、そのバインディングの内容を変更します。これの欠点は、別の種類のユーティリティウィンドウがある場合、ドキュメントウィンドウからそのユーティリティウィンドウへのバインディングも忘れずに接続する必要があることです。
- ウィンドウリストをトラバースして、最前面のドキュメントウィンドウを取得するアクセサをアプリケーションデリゲートに作成します。私のユーティリティウィンドウは、アプリケーションデリゲートのメソッドを介してバインドするだけです。ここでの欠点は、KVOに準拠していないことです
- アプリケーションデリゲートにゲッターとセッターを配置して、最前面のドキュメントを決定します(おそらく、KVOに準拠するように設定しますか?それは理にかなっていますか?)。おそらく、ウィンドウ通知を使用して、ウィンドウがメインステータスを失ったときにivarを適切な値に設定します。更新:私は今のところこれを使用しています、そしてそれは実際にはかなりきれいに見えます。ドキュメントウィンドウのwindowDidBecomeMain通知から値を設定し、windowWillCloseでそれをクリアします(現在の値の場合)。大きな異議がない限り、これはおそらく私が使用するアプローチです。
- 1つのアイデアは、mainWindow.windowController.documentにバインドすることでした...これは、共有ウィンドウがメインになると、このバインドがなくなることを除いて、近くなります。したがって、実際には、最前面のドキュメントウィンドウのコントローラー(および適切なクラス)を見つける必要があります。
これらのどれも完全に正しいようには見えません。私が見逃しているこれを行うためのより良い方法はありますか?
cocoa - Cocoa バインディングの問題。バインドされたテーブルの列にデータが表示されず、コンソールにエラーが表示されない
Cocoa プロジェクトを手動で同期されたインターフェイス モデルからバインディング モデルに変換するのに問題があるため、インターフェイスのグルー コードについて心配する必要はありません。
CocoaDevCentral Cocoa Bindings チュートリアルに従って、すべての基本をカバーしていることを確認しましたが、正しく動作しません。マスター/ディテール インターフェースを使用していますが、インターフェースのマスター部分を正しく動作させることさえできません。チュートリアルに示されている方法と同様のバインディング モデルを設定したにもかかわらず、マスター カラムにデータが表示されません。すべてのコントローラーとオブジェクトが-(id)key
、-(void)setKey:(id)key
メソッドをバインドに準拠するように変更し、nib に ControllerAlias オブジェクトを作成し、それをコントローラーに接続し、ControllerAlias が接続するクラスの NSMutableArrays の 1 つにバインドする NSArrayController を作成しました。配列内に含まれるオブジェクトの型を調べてから、テーブルの列を NSArrayController にバインドしました。
コンソールにエラーNSBindingDebugLogLevel
はまったく表示されず、1 に設定してもエラーは発生しません。これは、問題が何であるかを理解するのに役立ちます。
物事が正しく機能していることを確認するために私が考えることができる唯一のことは、NSArrayController に接続する NSMutableArray に実際に何かが含まれていることを確認することです。
助言がありますか?Cocoa バインディングには他に、チェックすべき典型的な落とし穴はありますか?
cocoa - 最新のプロジェクトに Cocoa バインディングを使用する必要がありますか?
バインディングの恩恵を受けると思われるプロジェクトを開始しています (ソース リスト テーブル、いくつかのブラウザー ビューなどがあります)。私の限られた経験から、バインディングはトラブルシューティングが難しく、非常に「魔法」であることがわかりました (たとえば、ログをどこにでも挿入して、どこが壊れているかを把握することは困難であり、すべてが機能するかしないかのどちらかです)。
これは私の経験不足の話ですか (その場合、座ってバインディングの理解に取り組むだけで時間を費やすことができ、物事がより明確/簡単になり始めることを期待できます)、またはすべてのグルーコードを自分で書いた方がよいでしょうか理解してトラブルシューティングできると確信していた方法。
cocoa - 奇妙なバインディングの問題
一部のデータを表すためにバインドを使用してブラウザー ビューを使用しようとしていますが、次のエラー メッセージが表示されます。
NSLog の出力に示されているように、これawakeFromNib
はアプリ コントローラーで が呼び出される前に発生し、BillingCode が displayString に対して KVC に準拠していることを知っていても発生します。
ツリー コントローラー -> 属性 -> オブジェクト コントローラーで "クラス" に設定された値に関連しているようです。そのクラスの名前を変更すると、エラー メッセージの名前が変更されます。奇妙なことに、呼び出されるまでオブジェクトを追加しないため、その時点でコンテンツ配列にオブジェクトがあってはなりませんawakeFromNib
。
cocoa - バインディングを使用して NSBrowserCell イメージを設定しますか?
NSTreeNode オブジェクトの配列にバインドされた NSTreeController に NSBrowser を接続しました。Content バインディングと Content Value バインディングを設定してツリー コントローラを適切に参照することで、テキスト部分を機能させるのは簡単ですが、バインディングを使用して各セルの画像を設定するにはどうすればよいでしょうか。
objective-c - NSBrowser で選択したセルのパスを使用して NSPathControl を更新し続けるにはどうすればよいですか
NSBrowser で現在選択されているパスを使用して NSPathControl を更新し続ける必要がありますが、パスが NSBrowser から変更されたときに通知を受け取る方法がわかりません。これを行う理想的な方法は、NSBrowser でパス キー パスを観察することですが、これにより、KVO は<key>
void メッセージを返し、更新を行わない set メソッドのみを観察できます (setPath は bool 成功値を返します)。
selectedCell キーパスも観察しようとしましたが、選択が変更されたときに通知が届きません。
私が見逃しているこれを行うための他の本当に明白な方法はありますか?
objective-c - MVCとココアバインディングのベストプラクティスの質問
ビューmyView、ビューコントローラーmyViewController、およびある種のモデルオブジェクトmyModelがあるとします。さらに、モデルに2つのKVO準拠のプロパティarrayOfPeopleNames
とarrayOfAnimalKinds
(両方のNSString)があるとします。
私の見解では、これら2つの配列の内容にバインドされた2つのポップアップが必要です。
私の質問は、myControllerにmyModelへの参照があり、ドロップダウンがmyViewControllerにバインドされている場合、myModel.arrayOfPeopleNames
?の行に沿ってキーパスを設定することをお勧めします。
または、myModelのNSArrayをミラーリングし、代わりにそのキーパスにバインドする追加のNSArrayをmyViewControllerに設定する必要がありますか?
前者は実装の観点からははるかに単純に見えますが(コントローラー配列をモデル配列にミラーリングする必要はありません)、モデルをビューに多く公開するかどうか疑問に思っています。
意見?
objective-c - bind:toObject:withKeyPath:options: をオーバーライドして NSView サブクラスでバインディングを実装する必要がありますか?
バインド可能にしたいプロパティを持つ NSView サブクラスがあります。サブクラスに以下を実装しました。
myView.h:
myView.m:
次に、arrayController へのバインディングを次のように作成します-[AppController awakeFromNib]
。
これはバインディングを実装する正しい方法ですか? それには多くの定型コードが含まれているため、何か間違ったことをしていると思います。
NSObject は手動で行ったことを自動的に実装すると思っていまし-bind:toObject:withKeyPath:options:
たが、そうではないようです。コメントアウトすると-bind:toObject:withKeyPath:options:
、setRepresentedObjects メソッドは呼び出されません。
追加情報:さらに調査を行った結果、元のアプローチは正しく、オーバーライドする必要があるという結論に達しました-bind:toObject:withKeyPath:options:
。Cocoa Bindings Programming Topics: How Do Bindings Work?からの引用です。:
bind:toObject:withKeyPath:options: メソッドでは、オブジェクトは少なくとも次のことを行う必要があります。
- 設定されているバインディングを特定する
- どのキーパスとどのオプションを使用して、どのオブジェクトにバインドされているかを記録します
- 変更の通知を受け取るために、バインドされているオブジェクトのキーパスのオブザーバーとして登録します
リスト 2 のコード サンプルは、角度バインディングのみを処理するジョイスティックの bind:toObject:withKeyPath:options: メソッドの部分的な実装を示しています。
リスト 2 ジョイスティック クラスの bind:toObject:withKeyPath:options メソッドの部分的な実装:
これは、Joystick クラス (NSView サブクラス) がオーバーライドする必要があることを明確に示しています-bind:toObject:withKeyPath:options:
。
これは驚くべきことです。これを実行するコード サンプルが他にないため、この結論には懐疑的でした。ただし、Apple の公式ドキュメントにはオーバーライドする必要があると記載-bind:toObject:withKeyPath:options:
されているため、これが正しいアプローチであると結論付けています。
誰かが私が間違っていることを証明できれば、とてもうれしいです!
objective-c - バインディングを使用した編集可能な NSTableView は、モデルに値を設定しません
これが私のセットアップです。
私のアプリケーション デリゲートには、currentFoo というプロパティがあります。currentFoo プロパティは、現在選択されている Foo インスタンスに設定されます。Foo インスタンスにはそれぞれ、結果と呼ばれる NSMutableArray であるプロパティがあります。結果のオブジェクトは、NSNumber、NSString など、さまざまなタイプにすることができます。
特定の時間に表示される NSTableView があり、ユーザーは currentFoo で結果のコレクションを確認できます。結果への追加と削除を可能にする UI もあります。
NSTableView には、NSArrayController の ArrangeObjects コントローラー キーにバインドされた単一の列があります。このバインディングで使用される NSValueTransformer サブクラスを作成して、結果配列で見つかったさまざまな可能な型を、表の列に表示する文字列表現に変換します。
NSArrayController のコンテンツ配列バインディングは、モデル キー パスとして currentFoo.results を使用して、NSObjectController の選択コントローラ キーに接続されます。最後に、NSObjectController はアプリケーション デリゲートからコンテンツを取得します。
これはすべてうまく機能し、 NSTableView で currentFoo.results を追加、削除、表示することは、私が望むように機能します。
私の問題は、テーブル ビューのコンテンツを編集しようとするときです。逆変換を許可するように NSValueTransformer サブクラスを設定し、reverseTransformedValue: を実装しました。コードをステップ実行すると、NSTableView 行の値を編集すると、値トランスフォーマーのメソッドに正しく送信され、変換されて返されることがわかります。
次に、バインディングが逆変換された値でモデルを更新しようとすると、エラーが発生します。
Cocoa バインディング: オブジェクト 0 のキー パスの値の設定エラー (バインドされたオブジェクト (null) から): [setValue:forUndefinedKey:]: このクラスは、キーのキー値コーディングに準拠していません。
したがって、基本的にはこの配列がテーブル ビューにバインドされており、ユーザーが行を編集するときに、文字列を適切なオブジェクトに変換したいと考えています。Cocoaバインディングでこのエラーが発生したため、NSTableColumnバインディングのキーパスに何かを設定する必要があると思いますが、何がわからないのですか。「自己」を試しましたが、うまくいきませんでした。
どんな助けでも大歓迎です。