I am working on Notification and my understanding on this is that IOS notifications like "textFieldShouldBeginEditing:(UITextField *)iTextField" gets posted only when you tap on a text field.
To my strange notice, my code is receiving this notification when I am tapping on "Back" button to go back to my previous view.
What are the possible chances of me getting this notification again. I believe we need not to register for such notifications. I have registered only for keyboard hide/show notifications.
Please suggest.
I found the issue. The issue was I was adding my textfield as first responder before server call and then was only removing it when you hit the return button or hit any other text field. That's why it was not getting resigned when back button was pressed. Now I have resigned it soon after server call.
Edit: I misunderstood the question. See the OP's answer.
Well, the keyboard will disappear upon navigation. It makes sense that the notification is posted in this case. One way to ignore notifications generated in response to view transitions is to keep track of your view controller's state.
- (void)viewWillDisappear:(BOOL)animated {
_transitioningView = YES;
}
- (void)viewDidDisappear:(BOOL)animated {
_transitioningView = NO;
}
- (void)viewWillAppear:(BOOL)animated {
_transitioningView = YES;
}
- (void)viewDidAppear:(BOOL)animated {
_transitioningView = NO;
}
Now, in the selector called by your keyboard notification, you can just return if the view is transitioning.
- (void)keyboardWillHide:(NSNotification*)notif {
if (_transitioningView)
return;
// Handle keyboard dismissal.
}
Related
I use this code in AppDelegate:
- (BOOL)accessibilityPerformMagicTap {
NSLog(#"Appdelegate = %s",__func__);
return YES;
}
When I click the home button and two-fingered double tap while using VoiceOver activates, this method is not invoked. What is the reason for this? How can I use this method with my music app?
You cannot. The method is called on the focused accessibility element while the app is foregrounded.
An app we made utilizes keyboardWillShow notifications from NSNotificationCenter
Everything was working as expected until we tried to use the app with a device that had the Sogou custom keyboard installed. When this keyboard is used (which oddly enough it doesn't seem to always come up -- for instance secure text entries ignore the Sogou keyboard) the keyboardWillShow notification is not firing.
Does anyone know of this issue or how to disable the use of custom keyboards?
The only way I found to get this to work was to disable all custom keyboards using the app delegate:
- (BOOL)application:(UIApplication *)application shouldAllowExtensionPointIdentifier:(NSString *)extensionPointIdentifier {
if ([extensionPointIdentifier isEqualToString: UIApplicationKeyboardExtensionPointIdentifier]) {
return NO;
}
return YES;
}
I have an animating sine wave in my app that needs to be reset when the user hits the home button or locks their phone (turning off the screen). Once the user brings the app back to the foreground, the sine wave animation is triggered again. This works fine until I realized it was occurring when the microphone access permission pops up. So the microphone access pops up, causing my app to go into the background and the animation to turn off, but the app is still visible. Any way I can know that the mic access pop up is occurring, so I can make some kind of if statement?
-(void) appDidEnterForeground:(NSNotification *)notification
{
if( viewIsUp == NO)
{
[self.sineWave.layer removeAllAnimations];
}
else
{
[self.sineWave animateWave];
}
}
-(void) appDidEnterBackground:(NSNotification *)notification
{
if(viewIsUp)
{
[self.sineWave.layer removeAllAnimations];
}
}
I accidentally set UIApplicationWillResignActiveNotification as the notification to call appDidEnterBackground. When the microphone access pop up would display, the only notification that would get called was UIApplicationWillResignActiveNotification. So when the home button was tapped or the screen was locked, I would remove the animation when UIApplicationDidEnterBackgroundNotification was called and when the mic access pop up displayed, I would leave the animation as it is when UIApplicationWillResignActiveNotification gets called. Worked out nicely. Hope this helps someone.
I’m getting multiple UIKeyboardDidShowNotification and UIKeyboardDidHideNotification notifications when I rotate the device and I can’t figure out why.
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. It works fine there too. However, when I rotate the device, I get multiple hide and show notifications. And I don’t know why.
Instead of getting one UIKeyboardDidHideNotification notification, I get a hide, a show, a hide, and then a show.
2:39:44.200 Picts for SLPs[16533:907] keyboardDidHide called. Keyboard showing flag is YES.
2:39:51.751 Picts for SLPs[16533:907] keyboardDidShow called. Keyboard showing flag is NO.
2:39:55.224 Picts for SLPs[16533:907] keyboardDidHide called. Keyboard showing flag is YES.
2:39:56.124 Picts for SLPs[16533:907] keyboardDidShow called. Keyboard showing flag is NO.
I posted the relevant code below. It is taken mostly from StackOverflow posts (Thanks guys).
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];
}
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];
}
}
resignFirstResponder sends a notification that closes the keyboard
- (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.
- (void)keyboardDidHide:(NSNotification *)notification {
NSLog(#"keyboardDidHide called. Keyboard showing flag is %#.", self.keyBoardIsShowing ? #"YES" : #"NO");
self.keyBoardIsShowing = NO;
// Move the text, update the database
}
- (void)keyboardDidShow:(NSNotification *)notification {
NSLog(#"keyboardDidShow called. Keyboard showing flag is %#.", self.keyBoardIsShowing ? #"YES" : #"NO");
self.keyBoardIsShowing = YES;
// Move the text
}
any chance you could manually dismiss the keyboard and clean up your database from within this method:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
and then if you want the keyboard brought back up once the rotation completes, manually call your method to display it from within:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
That may or may not fit your needs, but it's a pretty common and clean technique to "get out of the way" while Apple handles the rotation, and then get back to business once everything is back on solid ground again.
How to respond to starting dictation?
Known ways of responding to dictation:
dictationRecordingDidEnd - respond to the completion of the recognition of a dictated
phrase.
dictationRecognitionFailed - respond to failed dictation recognition.
Reference: UITextInput Protocol Reference
Starting in iOS 5.1, when the user chooses dictation input on a supported device, the system automatically inserts recognized phrases into the current text view. Methods in the UITextInput protocol allow your app to respond to the completion of dictation, as described in “Using Dictation.” You can use an object of the UIDictationPhrase class to obtain a string representing a phrase a user has dictated. In the case of ambiguous dictation results, a dictation phrase object provides an array containing alternative strings.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITextInput_Protocol/Reference/Reference.html
As far as I can tell, there's no public API for detecting when dictation has started.
If you really want to do it, and you want to be in the App Store, you can probably get away with the following approach, but it is totally unsupported, it might get you rejected anyway, and it is likely to break in a future version of iOS.
The text system posts some undocumented notifications after changing to or from the dictation “keyboard”. Two of them are posted both on a change to it and a change from it, with these names:
UIKeyboardCandidateCorrectionDidChangeNotification
UIKeyboardLayoutDidChangedNotification
Note that the second one has a strange verb conjugation. That is not a typo. (Well, it's not my typo.)
These notices are also posted at other times, so you can't just observe them and assume the dictation state has changed. You'll need to do more checking when you receive the notification. So, add yourself as an observer of one of those notifications. The first one seems less likely to go away or be renamed in the future.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(checkForDictationKeyboard:)
name:#"UIKeyboardCandidateCorrectionDidChangeNotification"
object:nil];
...
When you receive the notification, you'll want to see whether the dictation view is showing:
- (void)checkForDictationKeyboard:(NSNotification *)note {
if ([self isShowingDictationView]) {
NSLog(#"showing dictation view");
} else {
NSLog(#"not showing dictation view");
}
}
To see whether it's showing, check each window except your own application window. Normally, the only other window is the text system's window.
- (BOOL)isShowingDictationView {
for (UIWindow *window in [UIApplication sharedApplication].windows) {
if (window == self.window)
continue;
if (containsDictationView(window))
return YES;
}
return NO;
}
Recursively walk the view hierarchy checking for a view whose class name contains the string “DictationView”. The actual class name is UIDictationView but by not using the whole name you're less likely to be rejected from the App Store.
static BOOL containsDictationView(UIView *view) {
if (strstr(class_getName(view.class), "DictationView") != NULL)
return YES;
for (UIView *subview in view.subviews) {
if (containsDictationView(subview))
return YES;
}
return NO;
}
Although this question is answered, I still want to add my solution and wish to be helpful to someone else.
When you tap on the MIC button on the keyboard, primaryLanguage will change to dictation. You can detect that like this:
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(handleCurrentInputModeDidChange:)
name:UITextInputCurrentInputModeDidChangeNotification
object:nil];
- (void) handleCurrentInputModeDidChange:(NSNotification *)notification
{
NSString *primaryLanguage = [UITextInputMode currentInputMode].primaryLanguage;
NSLog(#"current primaryLanguage is: %#", primaryLanguage);
}
UPDATE:
Just as what #user1686700 said, currentInputMode already been deprecated. This isn't a solution any more.
Please note - UITextInputMode's currentInputMode is deprecated as of iOS7.
We may just have to wait until Apple decides to publish the dictation API so we can make the calls that make sense as per our intentions.