Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITextView subclass as delegate of itself

Let's say I add a UITextView to my UIView, and I want it to change its background color each time the contents change. I can do this by becoming the delegate of the UITextView and implementing textViewDidChange.

If I am using this behavior frequently though, it makes sense to create a UITextView subclass, which I will call ColorSwitchingTextView. It should include the color-switching behavior by default, so that any UIView can simply add it instead of a standard UITextView if it wants that behavior.

How do I detect changes in the content from within my ColorSwitchingTextView class? I don't think I can do something like self.delegate = self.

In summary, how can a UITextView subclass know when its contents change?

EDIT It seems I can use self.delegate = self, but this means that the UIViewController that uses the ColorSwitchingTextView can not also subscribe to the notifications. Once I use switchingTextView.delegate = self in the view controller, the subclass behavior no longer works. Any workarounds? I'm trying to get a custom UITextView that otherwise works like a regular UITextView.

like image 419
Ben Packard Avatar asked Nov 12 '12 00:11

Ben Packard


4 Answers

In your subclass, listen for the UITextViewTextDidChangeNotification notification and update the background color when you receive the notification, like this:

/* 
 * When you initialize your class (in `initWithFrame:` and `initWithCoder:`), 
 * listen for the notification:
 */
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(myTextDidChange)
                                             name:UITextViewTextDidChangeNotification
                                           object:self];

...

// Implement the method which is called when our text changes:
- (void)myTextDidChange 
{
    // Change the background color
}

- (void)dealloc
{
    // Stop listening when deallocating your class:
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
like image 147
lnafziger Avatar answered Nov 17 '22 05:11

lnafziger


Better to do it right way from the beginning.

What Apple and SOLID would suggest, is to subclass not the UITextView, but the UIView. In your custom UIColorTextView you will have member UITextView as subview and your UIColorTextView will be it's delegate. Further, your UIColorTextView will have it's own delegate and will pass required delegate callbacks from UITextView to it's delegate.

I had some task like this not with UITextView but with UIScrollView.

like image 24
eagle.dan.1349 Avatar answered Nov 17 '22 06:11

eagle.dan.1349


In your subclass, add self as an observer to UITextViewTextDidChangeNotification.

That said, I disagree with the ongoing conversation that setting self as the delegate is a bad idea. For this particular case, sure, but only because there's a better way (UITextViewTextDidChangeNotification).

like image 2
John Estropia Avatar answered Nov 17 '22 05:11

John Estropia


You can use NSNotificationCenter.

Set the delegate to self in the subclass (never tried this, but you said it works), then in the view controller you want to get notifications, do

[[NSNotificationCenter defaultCenter] 
         addObserver:self 
         selector:@selector(textFieldDidBeginEditing:) 
         name:@"TextFieldDidNotification" object:nil];

and in the subclass:

NSDictionary *userInfo = [NSDictionary dictionaryWithObject:self forKey:@"textField"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"TextFieldDidBeginEditingNotification" object:self userInfo:userInfo]

Now you can also pass any other info in the dictionary as well.

like image 1
Ali Hamze Avatar answered Nov 17 '22 06:11

Ali Hamze