I wrote most of this post for StackOverflow since I’m getting multiple UIKeyboardDidShowNotification and UIKeyboardDidHideNotification notifications when I rotate the device and I can’t figure out why. But it has a good example of how to do notifications in iOS so I thought I’d post it here.
I have an app that lets you edit the text for each picture. (it’s in a UITextView.) Most of the time I need to slide the text up so you can see it above the keyboard, then I slide it down when you are done editing. Then I do a database update to save the new text. I use notifications to tell me when the keyboard is displayed and when it goes away. It works fine on iPad when the user taps the keyboard close icon on the keyboard. It also works fine if the user swipes to the next page and iOS closes the keyboard. Since iPhones and iPods don’t have a keyboard close key, I wrote a method to close the keyboard when the picture or background is tapped.
In my class that displays the pictures I start notifications when it is initialized.
- (id)initWithParentView:(UIView *)parentview {
self = [super init];
if (self) {
_parentView = parentview;
if (ALLOW_DATABASE_EDITING) [self startNotifications];
}
return self;
}
- (void)startNotifications {
// Listen for keyboard appearances and disappearances
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:nil];
}
Note that the @selector() is the name of the method that is called when the notification center gets a notification.
The View Controller calls the hideKeyboard method in the View when the user taps on the picture.
- (void)dismissKeyboard {
if (self.showArtic.keyBoardIsShowing) {
[self.showArtic hideTheKeyboard];
}
}
<code>
resignFirstResponder sends a notification that closes the keyboard. When it hides a notification is sent and the keyBoardDidHide method is called.
<code class='smaller'>
- (void)hideTheKeyboard {
id <ShowArticDelegate> SA_delegate = _delegate;
// Don't update the database when there is no text.
if ( ![self.editableTextView.text isEqualToString:@""] ) {
[SA_delegate updateTextInDatabase:self.editableTextView.text];
}
[self.editableTextView resignFirstResponder];
}
These methods respond to the notifications. I use block animations to move the text up and back. I also shade the background so it stands out a bit, but the picture is still visible under the text block. The self.keyBoardIsShowing flag is used in the view controller to decide whether to tell the keyboard to hide when the picture is tapped.
- (void)keyboardDidShow:(NSNotification *)notification {
NSLog(@"keyboardDidShow called. Keyboard showing flag is %@.", self.keyBoardIsShowing ? @"YES" : @"NO");
self.keyBoardIsShowing = YES;
if (self.textShiftAmount > 0) {
self.editableTextView.backgroundColor = [UIColor colorWithRed:240/255.0f green:240/255.0f blue:240/255.0f alpha:.5f];
[self.parentView bringSubviewToFront:self.editableTextView];
[UIView animateWithDuration:.7
animations:^{
CGRect frame = self.editableTextView.frame;
frame.origin.y = self.pictButton.frame.origin.y + self.pictButton.frame.size.height - self.textShiftAmount;
self.editableTextView.frame = frame;
}
completion:^(BOOL finished){
}];
}
}
- (void)keyboardDidHide:(NSNotification *)notification {
NSLog(@"keyboardDidHide called. Keyboard showing flag is %@.", self.keyBoardIsShowing ? @"YES" : @"NO");
self.keyBoardIsShowing = NO;
id <ShowArticDelegate> SA_delegate = _delegate;
// Don't update the database when there is no text.
if ( ![self.editableTextView.text isEqualToString:@""] ) {
[SA_delegate updateTextInDatabase:self.editableTextView.text];
}
if (self.textShiftAmount > 0) {
self.editableTextView.backgroundColor = [UIColor whiteColor];
[UIView animateWithDuration:.7
animations:^{
CGRect frame = self.editableTextView.frame;
frame.origin.y = self.pictButton.frame.origin.y + self.pictButton.frame.size.height;
self.editableTextView.frame = frame;
}
completion:^(BOOL finished){
self.editableTextView.backgroundColor = [UIColor clearColor];
}];
}
}