16

I'm pretty new to mac development (coming from a web and iOS background) and I can't work out how I could get a notification every time the value of an NSTextView changes. Any ideas?

tshepang
  • 12,111
  • 21
  • 91
  • 136
tarnfeld
  • 25,992
  • 41
  • 111
  • 146

4 Answers4

39

Ups I just saw that you want a callback from NSTextView and not NSTextField

Just add in the header of the object which should be the delegate the protocol

@interface delegateAppDelegate : NSObject <NSApplicationDelegate, NSTextViewDelegate> {
    NSWindow *window;
}

After that you add a method like

-(void)textDidChange:(NSNotification *)notification {
    NSLog(@"Ok");
}

Make sure you connected the delegate property of the NSTextView (not NSScrollView) with the object which should receive the delegate

idmean
  • 14,540
  • 9
  • 54
  • 83
lbrndnr
  • 3,361
  • 2
  • 24
  • 34
  • That's it! I'm pretty sure this was one of the things I tried, but obviously didn't quite get it right. Its working now :-) Thanks! – tarnfeld Mar 05 '11 at 11:56
  • 2
    NSTextViewDelegate implements NSTextDelegate that's what that works but you could also use specific NSTextViewDelegate methods like - (BOOL)textView:(NSTextView *)aTextView shouldChangeTextInRange:(NSRange)affectedCharRange replacementString:(NSString *)replacementString – valexa Apr 24 '12 at 10:53
  • 8
    This will only get changes from the user interacting with the NSTextView directly (e.g. the user types in the textview or copies and pastes into it or cuts from it). It won't catch changes to the textView if you programmatically change the textView as in `textView.string = @"Foo";`. For that you need to be the delegate of the textview's textStorage, as in `textView.textStorage.delegate = self;` and implement `- (void)textStorageWillProcessEditing:(NSNotification *)aNotification` on the class of the object that is self. This well get both user-driven changes & direct property setter changes. – Joel Jan 07 '15 at 02:07
  • Thanks Joel, was having a bad time finding this info. – Ian Bytchek Sep 14 '16 at 18:20
5

Here's the solution:

NSTextView *textView = ...;

@interface MyClass : NSObject<NSTextStorageDelegate>
@property NSTextView *textView;
@end

MyClass *myClass = [[MyClass alloc] init];
myClass.textView = textView;
textView.textStorage.delegate = myClass;

@implementation MyClass
- (void)textStorageDidProcessEditing:(NSNotification *)aNotification
{
   // self.textView.string will be the current value of the NSTextView
   // and this will get invoked whenever the textView's value changes,
   // BOTH from user changes (like typing) or programmatic changes,
   // like textView.string = @"Foo";
}
@end
Joel
  • 2,285
  • 2
  • 21
  • 22
0

set the nstextfield's delegate. in the .h file of the delegate you add the delegate protocol In the .m file you add a method like -(void)controlTextDidChange:(NSNotification *)obj { NSLog(@"ok"); }

I hope that helps

lbrndnr
  • 3,361
  • 2
  • 24
  • 34
  • 1
    this is for NSTextField not NSTextView – valexa Apr 24 '12 at 11:01
  • NSTextView is a subclass of NSTextField and so is its delegates – keji Mar 16 '13 at 01:33
  • 3
    I'm afraid https://developer.apple.com/library/mac/documentation/cocoa/reference/applicationkit/classes/NSTextView_Class/Reference/Reference.html clearly shows NSTextView inherits from NSText which inherits from NSView. NSTextField inherits from NSControl which also inherits from NSView. controlTextDidChange is a delegate method of NSControl which means NSTextField has access to controlTextDidChange but NSTextView does not because it doesn't inherit from NSControl or NSTextField. – Winter Dragoness Feb 28 '14 at 17:34
-3

Set the delegate and then use

- (void) controlTextDidChange: (NSNotification *) notification
{
}
Craig
  • 89
  • 4