iOS Keyboard, VoiceOver and accessibilityViewIsModal - ios

I'm trying to make a inputAccessoryView AND the keyboard modal for VoiceOver users so they don't get lost. Setting:
view.accessibilityViewIsModal = YES;
textField.inputAccessoryView = view;
Makes the view modal with keyboard visible but unusable - it is outside of the modal view.
Next I tried this after the keyboard has appeared:
textField.inputAccessoryView.superview.accessibilityViewIsModal = YES;
Which seems a bit out of bounds but almost worked - but the keys physical after B (N, M space, etc) were not navigable.
Next up was this:
textField.inputAccessoryView.superview.superview.accessibilityViewIsModal = YES;
and everything works just fine. That view, BTW logs as follows:
<UITextEffectsWindow: 0x17170290; frame = (0 0; 320 568); opaque = NO; gestureRecognizers = <NSArray: 0x17170710>; layer = <UIWindowLayer: 0x17170430>>
My question is this: I this a stupid thing to do? Seems like it. Is it legal? UITextEffectsWindow is private, but I'm not actually using it, just taking advantage of the fact that it's a view.
Any input or ways to work around the problem would help.

It's not illegal, but it is safe to assume it will stop working in future versions of iOS.
For example, in iOS 6, a developer could get from a cell to its tableview by calling self.superview. In iOS 7, there is now a private-classed view in between.
You may want to take a more dynamic approach, like traversing up the view hierarchy until you find a view with the correct frame, or with all of the views you need as its subviews. A similar approach for the UITableViewCell problem can be found here.

Related

UICollectionView reload() issue with Focus state got out of sync in tvOS 15.4 and above

In my application I have a ViewController, In that view controller I have two CollectionViews - CollectionViewA and CollectionViewB in vertically format. And basically I have a design like calendar. In CollectionViewA - Displays the informations like, S.No, Image and favourite/unfavourite options. In CollectionViewB - Displays the program informations. So when I click the favourite option I'm reloading the collectionviews so that the collection view will get reload and update the informations in UI for favourite/unfavourite icon appearance.
So this is how the functionality works.
Now what happens is, this functionality works properly till tvOS 15.2. When we do the same functionality in 15.3 and above, there is an CollectionView scroll issue (i.e) when I click favourite for the item in row number 10 then after collectionview.reload() it automatically moves to the position from 10 to 5 or 3.
This automatic scroll issue is happening with the below error which is noted in log console.
Collection view focus state got out of sync. Expected (null) to be the
current managed subview but found <MyApp.CollectionViewCell:
0x114517ad0; baseClass = UICollectionViewCell; frame = (0 6532; 270
126); opaque = NO; tintColor = UIExtendedGrayColorSpace 0 0; layer =
<CALayer: 0x28339ab00>>.
Let me know if anyone can help me out from this issue!!!

How do I read this statement from my Xcode Debugger?

When I transition between view controllers, the two latest ones I have created, in the debug, I am getting a large string that I'm not quite able to get to the bottom of.
Can anyone point me in the right direction/ help me to understand this and find the problem I've made?
I have compared all of my documents/view controllers to my working/non-error ones and can't find anything obvious.
2019-02-12 18:47:20.879463+1300 Techsupport[15324:9474292] <UIView:0x7ff96154a2f0; frame = (0 0; 375 812); autoresize = W+H; tintColor =UIExtendedSRGBColorSpace 1 0.149131 0 1; gestureRecognizers = <NSArray:0x600002c474e0>; layer = <CALayer: 0x6000021d42c0>>'s window is not equal` to <Techsupport.EslViewController: 0x7ff9618fd800>'s view's window!
It's easier to read if you take out all the details about the view:
Techsupport[15324:9474292] <UIView>'s window is not equal to <Techsupport.EslViewController: 0x7ff9618fd800>'s view's window!
It's hard to know exactly what's going on without seeing some of your code, but fundamentally the view that the error is complaining about (located at 0x7ff96154a2f0) belongs to a view hierarchy in a window that's different from the one that the view controller's view is in.
Here are some things to consider:
How are each of these views created?
Do you expect to have two windows? (Most iOS apps only have one.)
What are you trying to do with the view in question?
A good way to start is to set a breakpoint at the spot where the error occurs, and then work backward until you figure out where the view in question comes from.
As #Sachin Vas said, "it looks like you have a segue which is set to trigger automatically and also programmatically in the code." he was correct, I did have a mistake where I had called the function programmatically as well as automatically. Thanks for everyone's help!

Why is userInteractionEnabled property not working on particular UIButton?

This is probably the most frustrating situation I've dealt with, and it probably has the simplest solution.
I've got this UIButton storeB that gets properly initialized during the viewDidLoad: call of my UIViewController. Before I create the button, I create 5 other buttons.
During viewDidLoad:, I run this method called setupFBConditions which determines whether my forwardB button object should have an alpha of 0.5 with userInteractionEnabled set to 0. When this is the case, the button looks and performs the way it's supposed (essentially, like it's not there).
Furthermore, during this particular animation that is performed on one of my UIView objects, I decided to set the userInteractionEnabled property of my restartB object to 0 (so that no interaction occurs during the animation. That performance is also successful.
However, when I decide to write:
storeB.userInteractionEnabled = NO;
storeB.alpha = 0.5;
at the start of the animation (with the intention to keep this state till the game finishes or restartB is tapped again), and NSLog the button object, the log says that the userInteractionEnabled property is NO and alpha is 0.5, just like it should be. However, at no point do these properties get reflected to the UI.
storeB is my not even my last view to be added to the hierarchy (although it is the last UIButton). I have no idea why these changes are not taking effect.
I'm not going to post any more code because there's nothing to post besides the two lines above. It's that apparently simple of a problem + solution.
************ UPDATE **************
Here is the log report at the end of one of my swipe gesture actions (after storeB.userInteractionEnabled = NO;):
<UIButton: 0x1585ae80; frame = (270 8; 42 42); alpha = 0.5; opaque = NO;
userInteractionEnabled = NO; layer = <CALayer: 0x15899da0>>
<UIView: 0x1592bba0; frame = (0 0; 320 568); layer = <CALayer: 0x15934ae0>>
The frame is correct, the alpha and interaction settings are correct, and the superview frame (0,0,320,568) is exactly what it's supposed to be.
*********** SECOND UPDATE **************
In case anyone finds this useful...check the _retainCount property of your UIView/UIButton and see if it looks unusually high when taking into account all the operations done to the object. My retain count was 4 when it should have been 2, so every time I changed the property (of what I thought was my first instance of storeB), it was actually only affecting the second instance (that I didn't even know existed).

UIView not redrawing, but elements become misplaced

I'm having an issue with my app's layout which is a bit tricky to explain. When the app first starts, this is what I'm showing:
After the user taps "Create Profile", I animate those buttons and show a registration form instead:
Needless to say, the buttons are now not in their "natural" position. Note, however, that the text fields are - that's where I have placed them in the storyboard, but when the view first loads I hide them. The animations are working great, but then I needed to scroll my view up when the user gives focus to a text field and the keyboard hides the field. The details of how to trigger the bug are a bit hard to explain, so I managed to boil it down to what seems to be a redraw event, except that it isn't... Let me try and explain that.
First of all, here's what happens when the keyboard is about to show:
- (void)keyboardWillShow:(NSNotification*)notification
{
CGRect frame = self.view.frame;
frame.size.height -= 1;
self.view.frame = frame;
}
Notice that this is a test only, probably the minimal I found that would still trigger the bug. All it does is resize the view. I would expect the view to be exactly as it was, with one less pixel, right? Wrong. Here's what I get:
That is, all elements returned to their "natural" positions, completely ignoring their previous positions. My first guess was that it would seem that the window is redrawing, so I tried this:
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
NSLog(#"View was drawn");
}
But this only triggers when the window is first drawn, not when this strange behaviour happens. To understand what I mean by "natural position", here's what I have in storyboard:
You can also see that I'm not using constraints and the underlying structure of my view:
The full code for the entire setup is quite extensive, so pretty much not practical at all to show. However, how I animate the subviews resumes to changing their frame as I did in keyboardWillShow, and setting their positions to whatever I need.
Any ideas?
So you're using storyboards and you have "Use AutoLayout" set to false for your entire storyboard?
In that case your app is using "struts and springs" style placement rules. You're going to have to debug those.
It's a bit hard to describe everything in a view controller in a post. It's easier to go over it in IB. Perhaps you can write a utility function that logs all the autoresizingMask values for the views in your view controller, and go over those, and perhaps post them here describing the autoresizingMask values for each view in your original post.

Why UISearchBar and its scope buttons are shown in one line?

I have seen Apple's example "TableSearch" that when touched its scope buttons come below the search bar.
http://developer.apple.com/iphone/library/samplecode/TableSearch/Introduction/Intro.html
But when I make my own it looks good at first but when I touch it looks like ugly, scope buttons and search bar are shown in the same line like this:
http://cl.ly/BN9
What do I have to do make it like "TableSearch" example in the iPad?
I am doing everything in IB and tried to modify the search bar programatically from the controller:
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.rowHeight = 88.0f;
self.tableView.contentOffset = CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height);
self.searchDisplayController.searchResultsTableView.rowHeight = self.tableView.rowHeight;
//BELOW DID NOT WORK:
CGRect b = self.searchDisplayController.searchBar.bounds;
self.searchDisplayController.searchBar.bounds = CGRectMake(b.origin.x, b.origin.y, b.size.width, self.tableView.rowHeight);
b = self.searchDisplayController.searchBar.frame;
self.searchDisplayController.searchBar.frame = CGRectMake(b.origin.x, b.origin.y, b.size.width, self.tableView.rowHeight);
//BELOW WORKS PERFECT BUT IS A PRIVATE METHOD, HENCE I AM NOT SUPPOSED TO USE IT
//[self.searchDisplayController.searchBar setCombinesLandscapeBars:NO];
}
Thanks in advance.
I've encountered this bug as well, and I've both filed a report with Apple and requested technical assistance. I'll let you know how it goes. In the meantime I'll give you a brief bit of background on this bug.
On the iPhone, to preserve precious vertical screen real estate in Landscape mode, the UISearchDisplayController sets the UISearchBar to combine its search bar and search field in a single horizontal layout. This works pretty well because of the increased horizontal size of the screen (480 points in Landscape). Unfortunately, it works not so well on the iPad, where in Landscape mode the UI change really isn't necessary in the first place because you have plenty of vertical real estate. You also still only have 320 pixels of horizontal display space in the master view of the UISplitViewController, not the increased 480 of the iPhone. The result is an iSore.
Presumably the problem is that UISearchDisplayController is behaving badly in its willRotateToInterfaceOrientation:duration‎: method. Specifically, it's not bothering to check whether it's on an iPhone or not before it sets the combinesLandscapeBars property on its UISearchBar. The private API kludge in your code works because it fixes that oversight in the UISearchDisplayController. But of course Apple will rain down the fury of the ancients on you for using undocumented APIs, so you can't. Really we're at the mercy of Apple on this one.
If you're willing to give up the eye-candy and convenience of UISearchDisplayController, you can use a UISearchBar sans UISearchDisplayController and manage aspects of presentation yourself. Obviously this requires a lot more code and would be pointless if Apple's API engineers did their jobs, but it will at least resolve the display bug.
If you're Apple you can use your own undocumented APIs, which is why Mail.app doesn't have this problem.
UPDATE
The bug report I've filed with Apple is #8344719.
Using the following code, you will not get warning:
if ([self.searchDisplayController.searchBar respondsToSelector:#selector(setCombinesLandscapeBars:)])
{
objc_msgSend(self.searchDisplayController.searchBar, #selector(setCombinesLandscapeBars:), NO );
}
When you set the bounds and frame for the searchBar, like for the frame here:
blabla.searchBar.frame = CGRectMake(b.origin.x,
b.origin.y,
b.size.width,
self.tableView.rowHeight);
it seems like there is a problem with height. Scope buttons require some space under the search bar, so you should increase the height of both bounds and the frame.
If you show and hide scope buttons on some event you need to adjust the frame size each time.
I'm getting this issue on an iPad, but I can get it to work if I insert this in my implementation file:
#synthesize tableView;
I'm guessing there is something bad with the XIB being loaded, but I don't know why this would fix it.

Resources