4

ビューコントローラーでキーダウンイベントを取得できるソリューションを見つけようとしています。ビュー コントローラーがデフォルトでレスポンダー チェーンの一部であるとは思いません。

これについての方法のサンプルをいただければ幸いです。VC をレスポンダー チェーンに追加してイベントを取得する方法について理解できるドキュメントを見つけるのに苦労しました。

ありがとう。

ミーク

4

3 に答える 3

3

次のようなものを実装できます。

-(void) globalKeyDown: (NSNotification *) notification 

メソッドをコントローラークラスに追加し、コントローラーのawakeFromNib ...またはloadViewメソッドにオブザーバーを追加するだけです

- (void)awakeFromNib
{
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(globalKeyDown:)
                                                 name:@"my_keyEvent" 
                                               object:nil];
}

あなたのビュークラスで

-(void)keyDown:(NSEvent *)theEvent
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"my_keyEvent"
                                                    object:theEvent
                                                  userInfo:@{@"sender":self}];
}
于 2013-11-15T00:30:25.810 に答える
2

NSViewControllerこれを行うデフォルトの方法はありません。ただし、これはサブクラス化によって実現できますNSView。基本的な考え方は次のとおりです。

  • ビュー サブクラスを作成すると、ビュー コントローラーをデリゲートとして設定し、イベントを処理するデリゲート メソッドを作成できます。
  • ビュー ヘッダーの先頭でデリゲート プロトコルを宣言できます。
  • ビュー ヘッダーをビュー コントローラー ヘッダーにインポートします。View Controller をプロトコルの実装として宣言します。
  • ビューkeyDownで、イベントをデリゲートに送信します。

もう 1 つの方法は、View Controller に投稿NSNotificationskeyDown、通知を観察して処理することです。他の方法も存在します。

Delegate メソッドを使用した NSView サブクラスの説明

以下は、1 つの必須メソッド (プロトコルに準拠する id プロパティ) をNSView使用してヘッダーでプロトコルを宣言するサブクラスを使用した委任の例です。IBOutletサブクラスは、NSView必要なときにいつでもこのメソッドをデリゲートに呼び出します。デリゲートが nil の場合、Cocoa では問題ありません。また、接線方向に、ビューの色のプロパティにIB_Designableとを追加したことに注意してください。IBInspectableこれにより、IB での設定が可能になり、10.10 SDK が必要になります。

アプリ デリゲートは実装ファイルにNSViewサブクラスをインポートし、.m ファイルの上部にあるクラス拡張子でプロトコルを採用しています。このセクションでは、メソッドも実装しています。AppDelegate.mAppDelegate@implementation

また、IB では、ウィンドウに を追加し、インスペクターでNSViewそのクラスをカスタム サブクラスに設定しました。NSView最後に、IBeventDelegate IBOutletのプロキシに設定します。AppDelegate

カスタム NSView サブクラス インターフェイス

#import <Cocoa/Cocoa.h>


@protocol EventDelegatingViewDelegate <NSObject>

- (void)view:(NSView *)aView didHandleEvent:(NSEvent *)anEvent;

@end

IB_DESIGNABLE
@interface EventDelegatingView : NSView

@property IBOutlet id<EventDelegatingViewDelegate> eventDelegate;
@property IBInspectable NSColor *fillColor;
@property IBInspectable NSColor *strokeColor;

@end

カスタム NSView サブクラスの実装

#import "EventDelegatingView.h"



@implementation EventDelegatingView

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent {return YES;}

    // The following two methods allow a view to accept key input events. (literally they say, YES, please send me those events if I'm the center of attention.)
- (BOOL)acceptsFirstResponder {return YES;}
- (BOOL)canBecomeKeyView {return YES;}

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    [self.fillColor set];
    NSRectFill(self.bounds);

    [self.strokeColor set];
    NSFrameRect(self.bounds);
}

    // Notice these don't do anything but call the eventDelegate. I could do whatever here, but I didn't.
    // The NICE thing about delgation is, the originating object stays in control of it sends to its delegate.
    // However, true to the meaning of the word 'delegate', once you pass something to the delegate, you have delegated some decision making power to that delegate object and no longer have any control (if you did, you might have a bad code smell in terms of the delegation design pattern.)
- (void)mouseDown:(NSEvent *)theEvent
{
    [self.eventDelegate view:self didHandleEvent:theEvent];
}

- (void)keyDown:(NSEvent *)theEvent
{
    [self.eventDelegate view:self didHandleEvent:theEvent];
}

@end

App Delegate (および eventDelegate!) の実装

#import "AppDelegate.h"
    // Import the view class and if there were other files that implement any protocol
#import "EventDelegatingView.h"

    // Declare protocol conformance (or more accurately, not only import that protocol interface, but say you're going to implement it so the compiler can nag you if you don't)
@interface AppDelegate ()<EventDelegatingViewDelegate>

@property (weak) IBOutlet NSWindow *window;

    // For the simplest demo app we don't even need this property.
@property IBOutlet EventDelegatingView *eventDelegatingView;

@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application
}

- (void)applicationWillTerminate:(NSNotification *)aNotification {
    // Insert code here to tear down your application
}

    // It's all right here. Receive a reference to a view and a reference to an event, then do as you like with them.
#pragma mark - EventDelegatingViewDelegate
- (void)view:(NSView *)aView didHandleEvent:(NSEvent *)anEvent
{
    NSString *interestingEventNote;

    switch (anEvent.type) {
        case NSKeyDown:
        case NSKeyUp:
        {
                // For simplicity we won't try to figure out the modifier keys here.
            interestingEventNote = [NSString stringWithFormat:@"%@ key was pressed.", anEvent.charactersIgnoringModifiers];
        }
            break;

        case NSLeftMouseDown:
        {
            interestingEventNote = [NSString stringWithFormat:@"Left mouse down at point %@ in window", NSStringFromPoint(anEvent.locationInWindow)];
        }
            break;

        default:
            break;
    }

    NSLog(@"%@ %@ aView=%@\n note=%@", self, NSStringFromSelector(_cmd), aView, interestingEventNote?interestingEventNote:@"Nothing worth noting");
}

@end

委任の力については以上です。基本的に、これは一種のコールバックであり、クラスを構築して、必要に応じて別の場所で何かを延期できるようにする優れた方法です。かなり怠惰でオープンで疎結合の方法で、一部のビジネス ロジックを適切な場所に移動します。

注:私のコード例は、アプリ デリゲートの使用を示しています。でも校長は同じ。ビュー コントローラーはデリゲートに過ぎず、好きなだけ追加することも、少しだけ追加することもできます。

于 2014-01-05T02:52:39.563 に答える