Programatically created NSTextField does not post controlTextDidChange

Discussion in 'Mac Programming' started by UniversalBinary, Mar 25, 2015.

  1. UniversalBinary macrumors newbie

    Joined:
    Mar 25, 2015
    #1
    Hi all,

    I am trying to create a custom control (an NSView subclass) that hosts a number of other controls that are created on the fly and positioned on the view at runtime.

    One of these controls is an NSTextField which is created in the init method, with code below:

    Code:
    _addressBar = [[NSTextField alloc] initWithFrame: ... ];
    [_addressBar setBordered:NO];
    [_addressBar setEditable:YES];
    [_addressBar setSelectable:YES];
    [_addressBar setFont:newFont];
    [_addressBar setTarget:self];
    [_addressBar setAction:@selector(_textFieldAction:)];
    [_addressBar setDelegate:self];
    [self addSubview:_addressBar];
    My class implements the NSTextFieldDelegate protocol.

    The problem is that the controlTextDidChange method is never called when I type in the field. I have checked that the delegate is assigned correctly and I have even tried adding my class as an observer of the NSControlTextDidChangeNotification but nothing works, it is as if my text field is not posting a text changed notification when I type in it.

    What have I missed?
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    Post the code that implements the protocol methods.
     
  3. UniversalBinary, Mar 25, 2015
    Last edited: Mar 25, 2015

    UniversalBinary thread starter macrumors newbie

    Joined:
    Mar 25, 2015
    #3
    Code:
    - (void)controlTextDidChange:(NSNotification *)aNotification
    {
        _buttonAction = kButtonShouldNavigate;
        [_certButton setImage:[NSImage imageNamed:@"ShineyGlobe"]];
        
        if ([[_addressBar stringValue] length] == 0)
        {
            [_button setEnabled:NO];
        }
        else
        {
            [_button setEnabled:YES];
        }
    }
    
    This is the only protocol method I have implemented, the one that is not being called, I have tried setting a breakpoint. I have not implemented any of the other protocol methods. My class has to implement NSTextFieldDelegate in its declaration or the compiler will complain when you pass it to setDelegate.
     
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    In a situation like this, I usually make a simplified test case for exploration. Its purpose is to confirm one's expectations (the essence of debugging).

    Here, it should implement all the delegate methods, not just one. The implementation need do nothing more than NSLog the method as being called.

    Since the NSView subclass is apparently the delegate (I'm guessing because you didn't show the inheritance of the code), the simplified test case will be the containing NSView. It should NSLog things that happen both before and after creating & adding the text field.

    Finally, post the code for the test case, in a form complete enough for someone else to test. E.g. post both the .h and .m.

    Also be sure to identify your OS version & Xcode version.

    It might also be useful to post the URLs of examples you've looked at or used, including any Apple sample code. "I'm doing it exactly like X", where X is the URL of a complete known-working example is a useful reference.
     
  5. AntoineLec macrumors newbie

    Joined:
    Jul 31, 2012
    #5
    Here is some code that does what is expected:


    Code:
    #import "CView.h"
    
    /*
    @interface CView : NSView <NSTextFieldDelegate>
    
    @end
    */
    
    @implementation CView
    
    - (void)drawRect:(NSRect)dirtyRect {
        [super drawRect:dirtyRect];
        [[NSColor orangeColor] set];
        NSRectFill(self.bounds);
    }
    
    
    - (instancetype)initWithCoder:(NSCoder *)coder
    {
        self = [super initWithCoder:coder];
        if (self) {
            NSTextField * textField = [[NSTextField alloc] initWithFrame:NSInsetRect(self.bounds, 20, 20)];
            [textField setDelegate:self];
            [textField setTarget:self];
            [textField setAction:@selector(anAction:)];
            [self addSubview:textField];
        
        }
        return self;
    }
    
    
    -(void)controlTextDidChange:(NSNotification *)obj {
        NSLog(@"%@", [[obj object] stringValue]);
    }
    
    -(void)anAction:(id)sender {
        NSLog(@"Now processing text");
    }
    
    @end
    
    Just drop a NSView and set its class to CView. There is no other code.

    controlTextDidChange is called when the text is changed, and anAction: is called when return is pressed. Nothing special.

    Are you sure that the code you wrote is even called ? Put a breakpoint after:

    [self addSubview:_addressBar];

    and check that everything is what it should be (in terms of Class)

    Also, double check for typos..
     

Share This Page