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
.
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];
}
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.
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).
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.