Keypads showing on different views, causes UIKeyboardLayoutAlignmentView constraint error - ios

I've had a crash report, it's a real edge case. I launch a pin security view from applicationWillEnterForeground (the feature is optional). However, I have some form sheets which I use in some situations in my app.
So the pin view is added as a subview on window and a keypad is presented.
When the form sheet is showing, it appears on top of the pin view (which is wrong) and an action on the form sheet causes a crash, when showing another keypad.
So I believe I need to dismiss any form sheets if the application resigns / becomes active.
I've looked into sending a notification to the form sheet in applicationWillEnterForeground, however I'll have to firstly determine if a form sheet is visible then add method to dismiss it every form sheet.
This seems a lot of work for an edge case, can anyone suggest an alternative approach?
For completeness here's the error...
The layout constraints still need update after sending -updateConstraints to <_UIKeyboardLayoutAlignmentView: 0x14e59b790; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = >. _UIKeyboardLayoutAlignmentView or one of its superclasses may have overridden -updateConstraints without calling super. Or, something may have dirtied layout constraints in the middle of updating them. Both are programming errors.
I've seen this...
NSInteralInconsistencyException - UIKeyboardLayoutAlignmentView
However, I'd still need to end editing in various form sheets, which I can't access from applicationWillEnterForeground.

OK, after researching the issue I discovered that I needed to observe the application state. On notification then check if various objects are load and if so, resignFirstResponder when the keyboard is shown (aka is editing) (I had a text field in an UIAlertView), dismiss an UIAlertView and then dismiss in the view controller used in dialog.
Shesh... so not as simple as I was hoping.
Although this is an edge case for me, I figured I should fix it.
I also found this which will dissmiss alertviews https://github.com/sdarlington/WSLViewAutoDismiss
Which will save me a lot of hassle in simpler scenarios.
Apparently since iOS4, Apple recommends cancelling UIAlertViews and UIActionSheets when an application becomes active.

Related

Is it possible that an iOS application can have more than one window?

I have been asked this question many times in the interview searched every where didn't get any proper answer.So finally posting this question here.
You may go through this.
Yes, you can have multiple windows. A key window is the one who receives the user input.
Starting with Rob's answer I played around a bit and would like to write down some notes for others trying to get information on this topic:
It is not a problem at all to add another UIWindow. Just create one
and makeKeyAndVisible. Done.
Remove it by making another window
visible, then release the one you don't need anymore.
The window that is "key" receives all the keyboard input.
UIWindow covers everything, even modals, popovers, etc. Brilliant!
UIWindow is always in portrait implicitly. It does not rotate.
You'll have to add a controller to the new window's root controller and let that handle rotation.
(Just like the main window) The window's level determines
how "high" it gets displayed. Set it to UIWindowLevelStatusBar to have it cover everything.
Set its hidden property to NO. A 2nd
UIWindow can be used to bring views on the screen that float on top of everything. Without creating a dummy controller just to embed that in a UIPopoverController.
It can be especially useful for iPhone where there is no popover controller but where you might want to mimic something like it.
And yes, it solved, of course, my problem: if
the app resigns activation, add a cover window over whatever is
currently shown to prevent iOS from taking a screenshot of your
app's current content.
Generally one application require only 1 UIWindow, but still there may be some scenarios where you need to use multiple UIWindow in one application.
For example, you wish to show a view on the top of system AlertViews, or can the default Keyboard.
UIWindows are the special UIViews, for which their display order is controlled by .windowLevel property.
You don't need to add a new UIWindow as a subview of any of view. You can simply create a new UIWindow and call either window setHidden:NO or window makeKeyAndVisible depend on the level, you have given to it.
There are three default window enum levels defined:
UIWindowLevelNormal
UIWindowLevelStatusBar
UIWindowLevelAlert
Of course it can have multiple windows. Just, only one to be displayed at a time, that's the keyWindow. You can have multiple windows stored in array or whatsoever, and make them keyWindow when you want to display them.
And, yeah, read the documentation #Mannopson suggested, it's very useful.

iOS Keyboard (inside UIRemoteKeyboardWindow) is Not Shown When UITextField Becomes First Responder in Touch ID Completion Block (iOS 10)

I've recently discovered a problem in my app that only seems to occur in iOS 10 where the system keyboard does not display when programmatically triggering a text field to become first responder inside of a completion handler -- specifically the completion handler I get back from a Touch ID attempt.
The crazy part of this issue is, even though the keyboard is not shown, the area on the iPhone where the keyboard normally would be is still responding to touch inputs as if the user is typing on the keyboard!
After doing a lot of investigation and debugging into the issue, I stumbled across the fact that the hidden property is set to YES on the private UIRemoteKeyboardWindow that gets created after becomeFirstResponder is invoked on the text field. In other situations where I bring up the keyboard, the value of that hidden property is set to NO.
Has anybody else run into this problem in iOS 10? If so, anybody found a solution to this? I tried manually setting the hidden value to YES on the window instance but that had no effect on it. I'm pretty much grasping at straws at this point.
Attachments:
Here's the output of the windows from the UIApplication instance when the text field becomes first responder outside of the Touch ID completion handler (pay close attention to UIRemoteKeyboardWindow):
And when the UITextField becomes the first responder inside the Touch ID handler...
First Update
So I did not consider the becomeFirstResponder being done on the main thread before that some have pointed out, but unfortunately, it did not resolve the issue -- however, I did make some additional discoveries. The hidden window issue seems to stem from outputting the details of the UIApplication instance's windows immediately after issuing the becomeFirstResponder action. After doing that, I set a breakpoint on the UITextField editing callback and proceed to interact with the keyboard (that is invisible) -- and when I output the window details, it doesn't seem like the hidden property is ever set to YES (which can possibly rule out that property being set as the cause of the issue), but I still have an invisible keyboard! I started debugging the view hierarchy and below is a screenshot of what it looks like when I examine the keyboard window:
Hopefully you guys can see what I discovered here which is that the keys are present but there appears to be some white view blocking them from sight. The thing is, I don't even see those white views on my app screen. I just see what normally sits behind the keyboard when it's present.
As a temporary workaround, call becomeFirstResponder after a delay fixed this, however, not happy with the hacky solution.
Looks like the issue occurring for different scenarios too - keyboard could be invisible even if you are selecting the textField manually after cancelling touchId alert.

How can I get the size of the keyboard on iPhone?

I want to get the keyboard size without using NSNotification. When I press the plus button, it can replace the keyboard with a custom UIView like this:
Then the plus button is pressed and the view loaded:
How can I achieve this?
I already made same rookie mistake like you want to do here. The problem is you will write a lot only to realize you do not want to avoid standard flow provided you by iOS team. For example you will definitely have a bad time dealing with issue like this one (there is additional bar which is part of standard keyboard for Chinese locale):
I solved this by using other people's work from DAKeyboardControl project. You do not need to attach observer (or if you use DAKeyboardControl - block) directly to your bar with buttons, but to your controller and check what user is trying to do and animate this bar accordingly. In the sources you can see how to get keyboard's animation duration and timing function. It may sound more complicated than it indeed is, just give it a try.

clearButton not working in UITextEditField

This is one of those "it was working a while ago" troubleshooting efforts.
I'm working on the document preview view controller, in which is a scroll view, which itself contains subclasses of UIView that represent each document. I'm modeling this pretty closely to how Keynote handles its document preview, except I build my scroll view horizontally and with paging. But the standard user experience is present: Long press on a document icon causes all document icons to start jiggling, nab bar has + button and Edit button, etc.
The issue at hand is that when you tap on the name of a document, I hide all the others, move the one being edited front and center, build a new text edit field, add it as a subview atop the real name label, and set it as first responder; but the
[editNameTextField setClearButtonMode:UITextFieldViewModeWhileEditing];
while correctly showing in the edit field is not taking any action when the user taps on the clear button.
I can't figure out what I may have done to cause this to not work -- it had been!
My first thought was that somehow my instance of this subclass is no longer the delegate for this text edit field. To try and confirm/deny that, I usurped a tap on the image view of the document preview to compare the delegate property to self, and it passes.
if (editNameTextField) {
NSLog(#"editNameTextField is still active");
if ([editNameTextField.delegate isEqual:self]) {
NSLog(#"we're still the delegate for the editNameTextField");
}
}
Editing the text within the edit field works fine. Pressing the Return/Done key correctly sends the delegate message textFieldShouldReturn:
While investigating this I implemented the delegate method textFieldShouldClear: just to write a log message if the method gets called (and return YES of course). It never gets called.
My next thought was that perhaps a subview had covered up the area where the clear button sits. So I implemented textFieldShouldBeginEditing: and used the opportunity to bring my the text field to the front. That didn't change anything either. I set a debugger breakpoint there to play a sound when it was called, and it got called, so I know my text edit field is frontmost.
I have only one troubleshooting strategy remaining: Go backwards through snap shots until it starts working again. Before doing that I thought I'd see if any of the more experienced folks out here have any suggestions of what to try next.
Where are you adding the textfield? As a subview of the scrollView? If you added the textfield and it is out of bounds of its parent view it won't receive any touches.
You can try and not call becomeFirstResponder and see if clicking it will show keyboard. Another possible error might be that the parent view of the UITextField has userInteractionEnabled = NO.
Without seeing more code I'm afraid I can not offer more solutions.

MFMailComposeViewController defaults to read-only mode

I'm trying to use the MFMailComposeViewController in an iPhone app I'm building, but I can't get it to work correctly. I was following the Apple's sample code MailComposer. As you can see in the sample, the MFMailComposeViewController lets you type in whatever message you want, and in the case of recipients you can either type the email addresses or pick them from your contacts. My implementation is exactly as in the sample, and the MFMailComposeViewController appears and disappears as expected. However, the controller seems to be in read-only mode; i.e., the user can't change any of the fields. I can change the values of the different fields programmatically before showing the controller, but once it's visible no modifications can be done to any of the fields. I have checked everything a bunch of times, but I can't find anything different between my implementation and Apple's. I'm stumped! Has anyone encountered this issue before? Any suggestions?
Thanks a lot for any help you all can provide!
Found the problem! A parent view controller in my application listens to shake gestures, which requires that view controller listening for shakes becomes the first responder. The parent view controller needs to call
[self resignFirstResponder];
before showing the MFMailComposeViewController. After adding that line, the MFMailComposeViewController worked like a charm.
In general, any view controllers listening for shake gestures should resign first responder before showing any other view controllers. Otherwise, the app will continue to respond to shake gestures even when the corresponding view controller is not visible, which can definitely lead to even worse problems than the MFMailComposeViewController showing up in weird read-only mode.

Resources