Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macos 如何检测NSTextField何时具有焦点或是否为';s精选可可粉的含量_Macos_Cocoa_Focus_Nstextfield_First Responder - Fatal编程技术网

Macos 如何检测NSTextField何时具有焦点或是否为';s精选可可粉的含量

Macos 如何检测NSTextField何时具有焦点或是否为';s精选可可粉的含量,macos,cocoa,focus,nstextfield,first-responder,Macos,Cocoa,Focus,Nstextfield,First Responder,我在NSTableCellView中有一个NSTextField,我想要一个事件,当我的NSTextField获得禁用多个按钮的焦点时通知我,我发现了以下方法: -(void)controlTextDidBeginEditing:(NSNotification *)obj{ NSTextField *textField = (NSTextField *)[obj object]; if (textField != _nombreDelPaqueteTextField) {

我在NSTableCellView中有一个NSTextField,我想要一个事件,当我的NSTextField获得禁用多个按钮的焦点时通知我,我发现了以下方法:

-(void)controlTextDidBeginEditing:(NSNotification *)obj{
    NSTextField *textField  = (NSTextField *)[obj object];

    if (textField != _nombreDelPaqueteTextField) {
        [_nuevaCuentaActivoButton   setEnabled:FALSE];
        [_nuevaCuentaPasivoButton   setEnabled:FALSE];
        [_nuevaCuentaIngresosButton setEnabled:FALSE];
        [_nuevaCuentaEgresosButton  setEnabled:FALSE];
    }
}
但它会在我的文本字段开始编辑时触发,正如上面所说的,我希望当我聚焦文本字段时,按钮被禁用,而不是当我已经开始键入时


编辑:要根据Joshua Nozzi收到的帮助来编写我的代码,它仍然不起作用

MyNSTextField.h

#import <Cocoa/Cocoa.h>
@class MyNSTextField;

@protocol MyNSTextFieldDelegate

@optional -(BOOL)textFieldDidResignFirstResponder:(NSTextField *)sender;
@optional -(BOOL)textFieldDidBecomeFirstResponder:(NSTextField *)sender;

@end

@interface MyNSTextField : NSTextField

@property (strong, nonatomic)           id <MyNSTextFieldDelegate> cellView;

@end
在我的viewcontroller指令decunteaswc.m上

#import "MyNSTextField.h"


@interface EdicionDeCuentasWC ()<NSTableViewDataSource, NSTableViewDelegate, NSControlTextEditingDelegate, NSPopoverDelegate, MyNSTextFieldDelegate>
@end


@implementation EdicionDeCuentasWC
#pragma mark MyNSTextFieldDelegate
-(BOOL)textFieldDidBecomeFirstResponder:(NSTextField *)sender{
    NSLog(@"textFieldDidBecomeFirstResponder");
    return TRUE;
}

-(BOOL)textFieldDidResignFirstResponder:(NSTextField *)sender{
    NSLog(@"textFieldDidResignFirstResponder");
    return TRUE;
}
#pragma mark --
@end
#导入“MyNSTextField.h”
@接口指令DECUNTASWC()
@结束
@实施法令
#pragma mark MyNSTextFieldDelegate
-(BOOL)textfield成为第一响应者:(NSTextField*)发送者{
NSLog(@“TextFieldDiBecomeFirstResponder”);
返回TRUE;
}
-(BOOL)textFieldDidResignFirstResponder:(NSTextField*)发送方{
NSLog(@“textFieldDidResignFirstResponder”);
返回TRUE;
}
#布拉格标记--
@结束

重要的是,在visual editor中,已经将我的所有NSTextFields更改为MyNSTextField类,并将委托设置为我的文件的所有者(EdicationDecuentAsWC)

我有一个自定义的
NSTextField
子类,它覆盖了
-becomeFirstResponder
-resignFirstResponder
。它的
-cellView
属性要求与声明
-textdidBeen/ResignFirstResponder:(NSTextField*)发送方的协议一致,但这足以让您大致了解情况。可以很容易地修改它,以发布控制器可以注册为观察者的通知。我希望这有帮助

- (BOOL)becomeFirstResponder
{
    BOOL status = [super becomeFirstResponder];
    if (status)
        [self.cellView textFieldDidBecomeFirstResponder:self];
    return status;
}

- (BOOL)resignFirstResponder
{
    BOOL status = [super resignFirstResponder];
    if (status)
        [self.cellView textFieldDidResignFirstResponder:self];
    return status;
}

我想我成功了。我试图对
nstextfield
进行子类化,以覆盖
becomeFirstResponder()
resignFirstResponder()
,但一旦单击它,
becomeFirstResponder()
就会被调用,
resignFirstResponder()
就会被调用。嗯?但搜索字段看起来仍在编辑中,焦点仍在上面

我发现,当您单击搜索字段时,搜索字段会成为第一响应者,但
NSText
将在稍后某时准备好,焦点将移到
NSText

我发现在准备
NSText
时,它被设置为
self.currentEditor()
。问题是当
成为第一响应者()
的调用时,
self.currentEditor()
尚未设置。因此,
becomeFirstResponder()
不是检测其焦点的方法

另一方面,当焦点移动到
NSText
时,将调用文本字段的
resignFirstResponder()
,您知道吗<代码>self.currentEditor()
已设置。所以,现在是时候告诉它的代表,文本字段得到了关注

接下来,如何检测搜索字段何时失去焦点。同样,它是关于
NSText
。然后,您需要聆听
NSText
委托的方法,如
textdidediting()
,并确保让它的超类处理该方法,并查看
self.currentEditor()
是否为空。如果是这种情况,
NSText
将失去焦点,并将其告知文本字段的代表

我提供了一个代码,实际上
NSSearchField
子类来做同样的事情。同样的原则也适用于
NSTextField

protocol ZSearchFieldDelegate: NSTextFieldDelegate {
    func searchFieldDidBecomeFirstResponder(textField: ZSearchField)
    func searchFieldDidResignFirstResponder(textField: ZSearchField)
}


class ZSearchField: NSSearchField, NSTextDelegate {

    var expectingCurrentEditor: Bool = false

    // When you clicked on serach field, it will get becomeFirstResponder(),
    // and preparing NSText and focus will be taken by the NSText.
    // Problem is that self.currentEditor() hasn't been ready yet here.
    // So we have to wait resignFirstResponder() to get call and make sure
    // self.currentEditor() is ready.

    override func becomeFirstResponder() -> Bool {
        let status = super.becomeFirstResponder()
        if let _ = self.delegate as? ZSearchFieldDelegate where status == true {
            expectingCurrentEditor = true
        }
        return status
    }

    // It is pretty strange to detect search field get focused in resignFirstResponder()
    // method.  But otherwise, it is hard to tell if self.currentEditor() is available.
    // Once self.currentEditor() is there, that means the focus is moved from 
    // serach feild to NSText. So, tell it's delegate that the search field got focused.

    override func resignFirstResponder() -> Bool {
        let status = super.resignFirstResponder()
        if let delegate = self.delegate as? ZSearchFieldDelegate where status == true {
            if let _ = self.currentEditor() where expectingCurrentEditor {
                delegate.searchFieldDidBecomeFirstResponder(self)
                // currentEditor.delegate = self
            }
        }
        self.expectingCurrentEditor = false
        return status
    }

    // This method detect whether NSText lost it's focus or not.  Make sure
    // self.currentEditor() is nil, then that means the search field lost its focus,
    // and tell it's delegate that the search field lost its focus.

    override func textDidEndEditing(notification: NSNotification) {
        super.textDidEndEditing(notification)

        if let delegate = self.delegate as? ZSearchFieldDelegate {
            if self.currentEditor() == nil {
                delegate.searchFieldDidResignFirstResponder(self)
            }
        }
    }

}
您需要将
NSSerachField
更改为
ZSearchField
,并且您的客户端类必须符合
zsearchfieldelegate
而不是
NSTextFieldDelegate
。这里有一个例子。当用户单击搜索字段时,它会扩展其宽度;当您单击另一个位置时,通过更改Interface Builder设置的
NSLayoutConstraint
的值,搜索字段会失去焦点并缩小其宽度

class MyViewController: NSViewController, ZSearchFieldDelegate {

    // [snip]

    @IBOutlet weak var searchFieldWidthConstraint: NSLayoutConstraint!

    func searchFieldDidBecomeFirstResponder(textField: ZSearchField) {
        self.searchFieldWidthConstraint.constant = 300
        self.view.layoutSubtreeIfNeeded()
    }

    func searchFieldDidResignFirstResponder(textField: ZSearchField) {
        self.searchFieldWidthConstraint.constant = 100
        self.view.layoutSubtreeIfNeeded()
    }

}
这可能取决于操作系统的行为,我在El Capitan 10.11.4上试过,结果成功了

代码也可以从Gist中复制。

我在上找到了以下代码

  • 第一个响应者是文本视图(字段编辑器是文本视图)
  • 字段编辑器是否存在
  • 文本字段是否为字段编辑器的委托
  • 它似乎起作用了

    - (BOOL)isTextFieldInFocus:(NSTextField *)textField
    {
        BOOL inFocus = NO;
    
        inFocus = ([[[textField window] firstResponder] isKindOfClass:[NSTextView class]]
                   && [[textField window] fieldEditor:NO forObject:nil]!=nil
                   && [textField isEqualTo:(id)[(NSTextView *)[[textField window] firstResponder]delegate]]);
    
        return inFocus;
    }
    

    以防万一,作为@sam概念的一个细微变化,我们可以观察到
    NSWindow.firstResponder
    属性本身,根据文档,它符合KVO。然后将其与
    textField
    textField.currentEditor()
    进行比较,以确定该字段是否聚焦。

    您尝试过吗?我唯一能想到的另一个选项是@Lance:与
    -controlTextDidBeginEditing:
    -相同的问题,也就是说,只有在更改控件的文本时才会调用它。OP想知道现场是否有第一响应者状态(大概是什么时候该状态是辞职的,编辑还是否)。@LanceBatson textfield应该开始编辑cocoa touch(iPhone/iPad)的一种方法,如果我没有错的话,我正在使用cocoa framework(MacOSX)@Jesus,你找到有效的解决办法了吗?@天哪,你找到解决办法了吗。好吧,我正在尽我最大的努力想办法,把我理解的代码写出来,如果我错了,请纠正我,因为这对我来说仍然不起作用。至少是为了成为第一反应者。我现在确实记得,我必须为最终编辑/辞职第一响应者做一些额外的工作(因为编辑时的第一响应者,我认为,可能是文本字段的字段编辑器)。在-becomeFirstResponder上设置一个断点,让我知道你发现了什么。也许我的代码错了,你能告诉我我的代码是否正确吗??如果没有,那么正确的编码方式是什么?这里的信息不够,对不起。正确使用调试器并确保一切都如预期的那样,没有捷径可走(因为您已经知道有些东西不符合预期,所以这是您要使用的第一个工具)。哟
    - (BOOL)isTextFieldInFocus:(NSTextField *)textField
    {
        BOOL inFocus = NO;
    
        inFocus = ([[[textField window] firstResponder] isKindOfClass:[NSTextView class]]
                   && [[textField window] fieldEditor:NO forObject:nil]!=nil
                   && [textField isEqualTo:(id)[(NSTextView *)[[textField window] firstResponder]delegate]]);
    
        return inFocus;
    }