How to overwrite textDidChange: method correctly? - objective-c

I subclassed NSTextField and overwrite the textDidChange: as:
- (void)textDidChange:(NSNotification *)notification
{
// ... My own operation
}
But when I drag a input text box into my .xib file and control drag another class to assign the delegate I found the delegate's controlTextDidChange: method was never called.
Now tryingto solve this problem, I tried two ways al below:
I. calling super:
- (void)textDidChange:(NSNotification *)notification
{
// ... My own operation
[super textDidChange:notification];
}
But I got an error in runtime: attempt to insert nil object from objects[0]
II. calling delegate's method
- (void)textDidChange:(NSNotification *)notification
{
// ... My own operation
if ([self.delegate responseToSelector:#selector(controlTextDidChange:)])
{
[self.delegate ...]; // <--- Opps, something not happerned here.
}
}
What not happerned? I expected that the auto-complete should display the controlTextDidChange: method at the position of ... above. But it did not, actually. I typed the method directly, compilation fail because method not found.
How should I make my sub-class call the delegate normally? How should I overwrite the textDidChange: method correctly?
Further question for Vytautas:
I am sure I was using NSTextField. And I set a break point inside controlTextDidChange: method. As it was called, I should have known.
I did control-drag the text field to the delegate object, and I print delegate object in the textDidChange: method, it was sure that the delegate was set correctly.
The other delegate methods, such as controlTextDidBeginEditing: were called correctly. But controlTextDidChange: not called
I tried comment out the over-written in the subclassed NSTextField class, then controlTextDidChange: was called.
Therefore I was quite sure that I am not overwritting the textDidChange: right. But I do not known how to fix it.
What made me confused mostly was that why auto-completion did not show the controlTextDidChange: method when I attempted to call it.
About the auto-completion, here is how it showed:
No - controlTextDidChange: method.
2nd further reply for Vytautas:
I tried calling '[self controlTextDidChange]' but it did not work, and error occurred (as highlighted below):

I can say that - controlTextDidChange: is called for sure.
Maybe there is something wrong with you bindings in your *.xib.
Also it can be that in *.xib you are using NSTextView, not NSTextField.
In this case - controlTextDidChange: won't be called for sure.
If that is the case then you should take a look to NSTextView, NSTextViewDelegate and NSTextDelegate. NSTextView delegate has an alternative method for this - textDidChange:

Related

NSTextField Subclass textDidEndEditing: Deleting Text

I have an NSTextFeild Subclass in which I would like to implement textDidEndEditing: to check after each edit if it is empty or not. The method is being called perfectly, but when I click into another NSTextField (or a subclass), all the text that was in the first textfield is immediately deleted. If I click out into the view, the text stays, but is deleted the next time i click into another textfeild. All I have in the method right now is an NSLog. Does anyone have any ideas as to why this could be happening?
#import "BufferTableCellViewTextField.h"
#implementation BufferTableCellViewTextField
- (void)textDidEndEditing:(NSNotification *)notification{
NSLog(#"END");
}
#end
You need to call -super:
- (void)textDidEndEditing:(NSNotification *)notification;
{
[super textDidEndEditing:notification];
NSLog(#"END");
}
This delegate method wouldn't be causing your problem. I'd look back to your subclass and check to see that you are not using any UITextField delegate methods that are expecting a YES response that you may have inadvertently changed the return responses for. It may be helpful to post you subclass so we can see what is going on in there too...

textDidChange vs controlTextDidChange

Can someone explain me why textDidChange isn't handling my delegate but controlTextDidChange works from NSTextField.
- (void)controlTextDidChange:(NSNotification *)aNotification{
NSBeep();
}
from
- (void)textDidChange:(NSNotification *)aNotification{
NSBeep();
}
controlTextDidChange: is the correct delegate method defined on NSTextField (inherited from NSControl).
textDidChange: is a method that, when called on NSTextField, makes it behave as if its text changed (including calling the above method). It is not a delegate method for you to implement.
It's a little inconsistent of Apple as they do have a textDidChange: delegate method on UISearchBarDelegate.
textDidChange: Informs the delegate that the text object has changed its characters or formatting attributes.
I'm guessing that means its font (text attributes) changes, and not the text inputted.

Mouse Down events in Objective-C

I know this question has been asked a lot before, but nothing will work for me. The following code will not do anything at all.
- (void) mouseDown:(NSEvent*)event {
NSLog(#"It worked!");
}
I have tried a lot of different methods to get this to work, including creating custom NSEvents in this way:
NSEvent *someEvent;
- (void) mouseDown:(NSEvent*)someEvent {
NSLog(#"It worked!");
}
This is my .h file:
#interface test : NSWindow <NSWindowDelegate> {
}
Would somebody explain how to make this do something?
Make sure your class inherits from NSWindow and conforms to the <NSWindowDelegate> protocol. Otherwise, that's just a method that happens to be named mouseDown, and nobody will ever call it.
Update: Change your header file so that it looks like this:
#interface test : NSWindow <NSWindowDelegate> {
}
In other words, don't put a prototype of mouseDown inside the interface definition, or anywhere else in the .h file.
In your implementation file (.m) put just the method:
- (void) mouseDown:(NSEvent*)someEvent {
NSLog(#"It worked!");
}
Assuming that you have logging turned on in the device (are you sure you can read NSLog output from elsewhere in your program?), you should see "It worked!" printed there.
I'm not an obj-C expert by any means, but I think by putting the mouseDown prototype inside the interface definition, you were basically creating your own custom mouseDown method which hid the "real" one. This indicated to the compiler that it should not call your mouseDown method on a window click.
Your subclass must have a parent class of NSResponder, otherwise you will not get any events.
You're overriding the NSWindow class, you should be overriding the NSView "contentView" of the NSWindow class to capture mouse events. Most of the decorations (NSViews) on the window outside of the contentView are private.
Just create a new NSView that overrides mouseDown, etc and add it as your content view to the NSWindow object.

Mouse Down events in Objective-C? [duplicate]

I know this question has been asked a lot before, but nothing will work for me. The following code will not do anything at all.
- (void) mouseDown:(NSEvent*)event {
NSLog(#"It worked!");
}
I have tried a lot of different methods to get this to work, including creating custom NSEvents in this way:
NSEvent *someEvent;
- (void) mouseDown:(NSEvent*)someEvent {
NSLog(#"It worked!");
}
This is my .h file:
#interface test : NSWindow <NSWindowDelegate> {
}
Would somebody explain how to make this do something?
Make sure your class inherits from NSWindow and conforms to the <NSWindowDelegate> protocol. Otherwise, that's just a method that happens to be named mouseDown, and nobody will ever call it.
Update: Change your header file so that it looks like this:
#interface test : NSWindow <NSWindowDelegate> {
}
In other words, don't put a prototype of mouseDown inside the interface definition, or anywhere else in the .h file.
In your implementation file (.m) put just the method:
- (void) mouseDown:(NSEvent*)someEvent {
NSLog(#"It worked!");
}
Assuming that you have logging turned on in the device (are you sure you can read NSLog output from elsewhere in your program?), you should see "It worked!" printed there.
I'm not an obj-C expert by any means, but I think by putting the mouseDown prototype inside the interface definition, you were basically creating your own custom mouseDown method which hid the "real" one. This indicated to the compiler that it should not call your mouseDown method on a window click.
Your subclass must have a parent class of NSResponder, otherwise you will not get any events.
You're overriding the NSWindow class, you should be overriding the NSView "contentView" of the NSWindow class to capture mouse events. Most of the decorations (NSViews) on the window outside of the contentView are private.
Just create a new NSView that overrides mouseDown, etc and add it as your content view to the NSWindow object.

Delegate methods of NSTextField using NSNotification

I have an NSTokenField in a window. I am using it to store tags related to a Core Data object. Right now I have it set up such that I can add tags to the objects, but I cannot delete them. I need a delegate method on the NSTokenField that can let me know when the user has moved the focus out of the NSTokenField. Since NSTokenField is a subclass of NSTextField I figured that I could use its delegate methods. It has two that I think could be useful:
- (void)textDidChange:(NSNotification *)aNotification
- (void)textDidEndEditing:(NSNotification *)aNotification
I set my controller class as the delegate of my NSTokenField and put both of these methods into my controller class. I put a basic NSLog into each of them and neither is triggered when I interact with the NSTokenField. I am guessing it has something to do with NSNotification. How do I activate these methods?
The NSTokenField invokes the controlTextDidChange: and the controlTextDidEndEditing: notifications; change the two methods above, implementing them as:
- (void)controlTextDidChange:(NSNotification*)aNotification
{
//Code here..
}
- (void)controlTextDidEndEditing:(NSNotification *)aNotification
{
//Code here..
}