2012-02-05 21 views
5

Tôi thực sự muốn chế độ xem tùy chỉnh của mình hoạt động với -moveLeft:, -deleteForward:, -selectAll:, v.v., nhưng tôi cũng muốn chuyển bất kỳ khóa nào mà tôi không quan tâm đến việc chuyển tiếp chuỗi trả lời. Ngay bây giờ tôi đang ghi đè -keyDown: để gọi [self interpretKeyEvents:[NSArray arrayWithObject:event]];, nhưng điều này có vẻ như hog tất cả các sự kiện chính, ngay cả những sự kiện mà quan điểm của tôi không phản hồi.Xem explainKeyEvents: nhưng chuyển những người không mong muốn lên chuỗi trả lời?

Có cách nào để truyền các sự kiện không mong muốn lên chuỗi không, nhưng vẫn trả lời -moveLeft:, v.v ...? Hoặc tôi có cần phải thực hiện tất cả các hành động của riêng mình trong -keyDown: để tôi biết những gì tôi đã làm và không phản hồi không?

+0

Hãy thử [Giải pháp] của tôi (http://stackoverflow.com/a/23897022/1067147) – WINSergey

Trả lời

6

Đến đây, hãy cố gắng tìm ra giải pháp cho cùng một vấn đề này. Không bao giờ tìm thấy bất cứ điều gì trực tuyến, nhưng tôi đã đưa ra một cái gì đó mà dường như làm việc tốt cho đến nay. Dưới đây là những gì tôi đang thực hiện:

Phân lớp NSTextView của bạn (hoặc bất kỳ thứ gì bạn đang sử dụng) và tạo một biến mẫu để tạm thời lưu sự kiện quan trọng. . .

@interface MyTextView : NSTextView { 
    NSEvent* _keyDownEvent; 
} 

@end 

Sau đó xác định phương pháp của cái nhìn của bạn như vậy (đưa ra các giữ lại/phát hành rác nếu bạn đang sử dụng tính tham khảo tự động):

@implementation MyTextView 

- (id)initWithFrame:(NSRect)frame { 
    if (self = [super initWithFrame:frame]) { 
     _keyDownEvent = nil; 
    } 

    return self; 
} 

- (void)keyDown:(NSEvent*)event { 
    [_keyDownEvent release]; 
    _keyDownEvent = [event retain]; 
    [super keyDown:event]; 
} 

- (void)doCommandBySelector:(SEL)selector { 
    if (_keyDownEvent && selector == @selector(noop:)) { 
     if ([self nextResponder]) { 
      [[self nextResponder] keyDown:[_keyDownEvent autorelease]]; 
     } else { 
      [_keyDownEvent release]; 
     } 
     _keyDownEvent = nil; 
    } else { 
     [super doCommandBySelector:selector]; 
    } 
} 

- (void)dealloc { 
    [_keyDownEvent release]; 

    [super dealloc]; 
} 

@end 

Đây là cách tôi đến đây. Khi một phím bấm không được xử lý, bạn sẽ nghe thấy một âm báo bíp. Vì vậy, tôi thiết lập một breakpoint trên NSBeep(), và khi chương trình đã phá vỡ, tôi nhổ ra một chồng dấu vết trong GDB:

#0 0x00007fff96eb1c2d in NSBeep() 
#1 0x00007fff96e6d739 in -[NSResponder doCommandBySelector:]() 
#2 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#3 0x00007fff96fda826 in -[NSWindow doCommandBySelector:]() 
#4 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#5 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#6 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#7 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#8 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#9 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#10 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#11 0x00007fff96f486ce in -[NSTextView doCommandBySelector:]() 
#12 0x00007fff96da1c93 in -[NSKeyBindingManager(NSKeyBindingManager_MultiClients) interpretEventAsCommand:forClient:]() 
#13 0x00007fff970f5382 in -[NSTextInputContext handleEvent:]() 
#14 0x00007fff96fbfd2a in -[NSView interpretKeyEvents:]() 
#15 0x00007fff96f38a25 in -[NSTextView keyDown:]() 
#16 0x0000000100012889 in -[MyTextView keyDown:] (self=0x1004763a0, _cmd=0x7fff972b0234, event=0x100197320) at /path/MyTextView.m:24 
#17 0x00007fff96a16b44 in -[NSWindow sendEvent:]() 
#18 0x00007fff969af16d in -[NSApplication sendEvent:]() 
#19 0x00007fff969451f2 in -[NSApplication run]() 
#20 0x00007fff96bc3b88 in NSApplicationMain() 
#21 0x00000001000015e2 in main (argc=3, argv=0x7fff5fbff8f0) at /path/main.m:12 

gì đang xảy ra là thế này: Khi sự kiện phím không được sử dụng để nhập văn bản , lệnh "noop" được gửi lên chuỗi phản hồi. Theo mặc định, điều này sẽ kích hoạt tiếng bíp khi nó rơi ra khỏi chuỗi phản ứng. Trong giải pháp của tôi, lớp con NSTextView nắm bắt lệnh noop và thay vào đó ném sự kiện keyDown gốc xuống chuỗi phản hồi. Sau đó, NSWindow hoặc các chế độ xem khác của bạn sẽ nhận được bất kỳ sự kiện keyDown không được sử dụng nào như bình thường.

3

Đây là thực hiện nhanh chóng của tôi về câu trả lời @ daxnitro, và dường như làm việc:

import Cocoa 

class EditorTextView: NSTextView { 

    private var keyDownEvent: NSEvent? 

    required init?(coder aCoder: NSCoder) { 
     super.init(coder: aCoder) 
    } 

    override init() { 
     super.init() 
    } 

    override init(frame frameRect: NSRect, textContainer aTextContainer: NSTextContainer!) { 
     super.init(frame: frameRect, textContainer: aTextContainer) 
    } 

    override func keyDown(event: NSEvent) { 
     keyDownEvent = event 
     super.keyDown(event) 
    } 

    override func doCommandBySelector(aSelector: Selector) { 
     if aSelector != NSSelectorFromString("noop:") { 
      super.doCommandBySelector(aSelector) 
     } else if keyDownEvent != nil { 
      self.nextResponder?.keyDown(keyDownEvent!) 
     } 
     keyDownEvent = nil 
    } 

} 
Các vấn đề liên quan