Trouble with UIScrollView in iOS 8 GM - user-interface

I'm developing and iOS app which I started with iOS 7 and now tried to migrate to iOS 8. Everything works nicely except UIScrollViews. My app has a navigation bar and it seems to affect to UIScrollViews. Indeed, the content inside the view is pulled down the approximate space that a navigation bars occupies. The weird thing is that the same app running on iOS 7 doesn't cause any sort of problem related to that.
I've made a simple code to test if the problem was my app, but the problem is still there. Here it is my code:
UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 65, self.view.frame.size.width, self.view.frame.size.height-65)];
scroll.layer.borderWidth = 2.0f;
scroll.layer.borderColor = [UIColor greenColor].CGColor;
[self.view addSubview:scroll];
UIImageView *image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"searching1.png"]];
[scroll addSubview:image];
image.frame = CGRectMake(100, 0, 100, 100);
And that's the result, as you can see the image is not at point (0, 100):
I don't know how to deal with this problem. Moreover, iOS 8 is now in GM, so I don't know if this is a real bug or a SDK change.

The error was caused by the propety
self.automaticallyAdjustsScrollViewInsets
Turns out that in iOS 7 it was automatically set to false, but now in iOS it is true by default. So setting it explicitly to false solved the problem and the app is running well in both platforms.

Related

iOS9: UIDatePicker with datePickerMode of UIDatePickerModeTime only shows Hours, and no Minutes

I'm using Xcode beta 7 with the iOS9 simulator.
Using a UIDatePicker with a datePickerMode of UIDatePickerModeTime only shows Hours, and not minutes.
See screenshot:
On iOS 7 and 8, obviously it works as expected, and shows both Hours and Minutes. Screenshot:
I really do not want to reinvent the wheel and roll my own time picker. Any ideas on why this might be happening and how to fix? I can't find anything on google.
thanks,
Alex
I encountered this after the public release of iOS 9.0 with a UIDatePicker using UIDatePickerModeDate in my tableview.
I hacked around it by changing the UIDatePicker mode right before it was displayed, and then changing it back to the desired one:
[myDatePicker setDatePickerMode:UIDatePickerModeDateAndTime];
[myDatePicker setDatePickerMode:UIDatePickerModeDate];
I'm guessing redrawing it solves the issue. For interest's sake I don't think it's actually an issue of not displaying the minutes but rather a bug in the subviews because this is what mine looked like:
Inspecting using FLEX, this is part of the UIDatePicker that has a solid white background.
Found a useful description of this problem in the iOS 9 release notes - seems I should be reading these more carefully.
UIPickerView and UIDatePicker are now resizable and adaptive—previously, these views would enforce a default size even if you attempted to resize them. These views also now default to a width of 320 points on all devices, instead of to the device width on iPhone.
Interfaces that rely on the old enforcement of the default size will likely look wrong when compiled for iOS 9. Any problems encountered can be resolved by fully constraining or sizing picker views to the desired size instead of relying on implicit behavior.
iOS 9 Release Notes
In my case all I had to do was remove all constraints on the UIDatePicker and then "Reset to Suggested Constraints". Rebuild and now all is well.
I had an issue when upgrading Xcode to 7.0.
When the UIDatePicker was displayed the middle portion was blank, as per LordParsley's answer.
The height of the UIDatePicker for iOS 9 is 216; whereas earlier versions the height is 162, and forcing the height to 162 resolved the issue.
Since my view is defined within a storyboard, I setup a height constraint on the UIDatePicker and set the height to 162 for iOS versions < 9.0, within the view's viewDidLoad.
- (void) viewDidLoad {
[super viewDidLoad];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 9.0) {
//
// NOTE: iOS 9, or Xcode 7, now sets UIDatePicker height at 216; whereas,
// iOS 8, or Xcode 6.x, set it at 162.
//
// If the height is left at 216, then on iOS 7.1, the middle portion of the
// UIDatePicker control is missing. Setting the hieght to 162 fixes the issue
// within this application.
//
// UIDatePicker frame cannot be used to adjust the size, therefore use a
// height contraint to change the size.
//
self.dateHeightConstraint.constant = 162;
}
}
#LordParsley solution did the trick.
Just some additional details:
I notice it occurs on iPhone 5 series and not on iPhone 6/6 plus with leading and trailing constraints. Apparently the bug only appears when its frame width is 320. Probably its a miscalculation of picker subviews that causes the overlaps. This is quite funny because Apple is the one who set the default value and yet they've oversaw the issue.
Anyways I hope this gets resolved with iOS 9.1 which is now in beta.
I have same issue when running my app in iOS 9, my app using UIDatePicker in .xib file.
I resolved this problem by add it in code behind:
UIDatePicker* picker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 44, 320, 162)];
[self.view addSubview:picker];
I think, this's problem with new font San Francisco (the font is big than Helvetica) and .xib file.
Hope this help.
Thank!
On iPhone 5S iOS 9.1 my month names are truncated when I display the UIDatePicker. I fixed this problem by setting a local property as follows:
NSLocale *uk = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
NSCalendar *cal = [NSCalendar currentCalendar];
[cal setLocale:uk];
[_backdateDatePicker setCalendar:cal];

UIAlertview is showing in portrait mode when screen is in landscape mode

I have an application that is configured to support Portrait mode only. But I have to show one screen (say abcViewController) in my application in landscape mode. When abcViewController screen is pushed ,orientation changes from Portrait mode to Landscape mode. In that abcViewController screen statusBar, all images ,buttons are shown in landscape mode but UIAlertView is displayed in PortraitMode.
This means everything on view changes to landscape mode in abcViewController but UIAlertView doesn’t rotate to Landscape mode and remain in Portrait Mode.
I would like the UIAlertView to follow the rules of the containing view controller and show same orientation as statusBar.
Note: I m running my app on iOS 8.0 using Xcode 5.0 and I am searching for the solution which supports Xcode 5.0
Actually, I rotated UIView and status bar of this class programmatically for iOS 7 and earlier iOS versions,but I was having this problem of orientation problem in iOS 8, then I read a new change of iOS 8 which is related to orientation which is given below:
I ran the following code in both iOS 7 and iOS 8:
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
BOOL landscape = (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight);
NSLog(#"Currently landscape: %#, width: %.2f, height: %.2f",
(landscape ? #"Yes" : #"No"),
[[UIScreen mainScreen] bounds].size.width,
[[UIScreen mainScreen] bounds].size.height);
The following is the result from iOS 8:
Currently landscape: No, width: 320.00, height: 568.00
Currently landscape: Yes, width: 568.00, height: 320.00
Comparing to the result in iOS 7:
Currently landscape: No, width: 320.00, height: 568.00
Currently landscape: Yes, width: 320.00, height: 568.00
so, I got to know [UIScreen mainScreen].bounds.size becoming orientation-dependent in iOS8.
After reading this new change of iOS 8 I created a new class for iOS 8, so you have two solutions for this issue.
Solution 1: You should use UIAlertController instead of UIAlertView.
Solution 2: You can create a new class for iOS 8 for which you are facing this orientation issue.

Unexpected nil window in _UIApplicationHandleEventFromQueueEvent

One of my old apps is not working with iOS8. When I start the app up, and try to tap on the screen anywhere, I get this message in my console:
unexpected nil window in _UIApplicationHandleEventFromQueueEvent,
_windowServerHitTestWindow: <UIWindow: 0x7fe4d3e52660; frame = (0 0; 320 568);
opaque = NO; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x7fe4d3e2c450>;
layer = <UIWindowLayer: 0x7fe4d3e86a10>>
I'm using an old style MainWindow.xib. In the MainWindow.xib is my Window object, as well as a UINavigationController which has its first View Controller defined within as well. The image below is showing the Outlets connected to the App Delegate.
The white "view" in the screenshot below is the UIWindow. The view on the right is the UINavigationController (nav bar hidden) with the first ViewController defined inside it.
How do I fix this without recreating the entire app from scratch with a new project?
EDIT: I just discovered there is a TINY strip wherein my buttons will actually receive their taps/clicks.
I've also noticed that my self.view.window is nil. How do I make sure that is set?
Additional to B H answer. Also look this answer.
Got this issue when launching my landscape only app from portrait orientation (also the app shouldn't be presented in recently opened apps list, which can be seen by pressing Home button twice. Perhaps, iOS somehow caches the orientation and window size).
My code was
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window makeKeyAndVisible];
I set W+H autoresizing mask for window, it didn't help me, because the window don't being resized on rotation, but the transform matrix is changed.
The solution is simple
self.window = [UIWindow new];
[self.window makeKeyAndVisible];
self.window.frame = [[UIScreen mainScreen] bounds];
So the frame is set AFTER the window get its orientation from root view controller.
You don't have to add any code to fix this.
Open the main xib file and find "Window" from the left side and enable Visible at Launch and Full Screen at launch.
Check out your Window nib file and make sure it is taking up the full screen. I had a similar issue on my app where touch events weren't being registered on a strip on the right side. Once I set my MainWindow.xib to take up the Full Screen, I had no more errors and touch events were working again. My app was also being displayed in Landscape but my MainWindow.xib had portrait dimensions.
Sometimes it's just simple setting that's missing some value: Click on Project(whatever you named your project) name item then make sure General tab is selected and scroll to the bottom. Look for App icons and Launch Images make sure there is some value in the Launch Screen File field, this should be either Main or LaunchScreen
In case somebody finds this useful:
In my case, I had used
self.window = [[UIWindow alloc] init];
instead of
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
and that was the reason for the problem.
I was getting this error on an old app that did not have the Default-568h#2x.png launch screen. When the taller iPhones were first introduced, this was the signal to iOS that the app could handle the new geometry. Otherwise, it was displayed in a 320x480 window. Funny, I did not even notice the app was not using the full screen.
I wasn't able to test efpies solution, but the way I fixed it in my app was to replace the MainWindow.xib with a Storyboard.
We had the same issue, and we tried the proposed solutions in this thread without success.
What ended up working for us, was to re-write the logic to be pure programmatically instead of using xib's. After this we don't see the 'unexpected nil window' error and the view is getting the hit all over the screen.
In case this helps anyone else that stumbles here, I also got this error when I had the UIScreen.mainScreen().bounds size flipped when setting the window's frame.
I am also upgrading my old project to iOS 7 and iOS 8.
Actually, I don't use MainWindow.xib, but creating window manually in application:didFinishLaunchingWithOptions:.
But i have same unexpected nil window in _UIApplicationHandleEventFromQueueEvent error after launch.
So, in my case, problem was solved by changing deployment target to 6.0 and replacing code in main.m:
Old main.m:
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
New main.m:
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([YourAppDelegate class]));
}
}
In my case it was an old code and after reading the complete code i found this line
UIApplication.shared.delegate?.window??.isUserInteractionEnabled = false
I handle it according to my logic and it's working now.
It worked for me to Enable windows user interaction.
window.isUserInteractionEnabled = true
Using the new ios 8 'nativeBounds' UIScreen property instead of 'bounds' when creating the window fixed the issue for me. No other changes required.
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] nativeBounds]] autorelease];
To support previous version too, I do a runtime check with the version:
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

UISwitch doesn't work on Google Maps SDK for iOS?

I'm trying to create a UISwitch laid on mapView_ of Google Maps for my iOS app, but it seems not to work.
In details, I first followed instruction from google, created mapView_, then made it my viewcontroller's view:
self.view = mapView_;
Then, I created an UISwitch programmatically and added it as a subview:
mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(50, 360, 0, 0)];
[mySwitch setBackgroundColor:[UIColor clearColor]];
[mySwitch addTarget:self
action:#selector(changeSwitch:)
forControlEvents:UIControlEventTouchDown];
[mapView_ addSubview:mySwitch];
But when I touched the switch both in simulator and device, it didn't change its state from ON->OFF or OFF->ON. I even tried different UIControlEvent, such as UIControlEventValueChanged but it didn't work. To make sure that the code should work, I tried on a normal view of a normal test viewcontroller (that means, not using google maps), it worked fine!
Does anyone have any comment about this issue?
Thanks heaps!
You can work around this issue by adding both the UISwitch and the GMSMapView to a single UIView parent, instead of adding the UISwitch as a child of a GMSMapView. Yes, this means you need to position both the GMSMapView and the UISwitch.

iOS6 ScrollBarShouldScrollToTop not firing/ ScrollView Delegate issue

I am adding a dummy ScrollView to my app to detect a user click on the status bar, to performa an event in my program.. I am creating it in the ViewDidLoad:
//Dummy Scroll is for the tap on status bar to work
UIScrollView *dummyScrollView = [[UIScrollView alloc] init];
dummyScrollView.delegate = self;
[[self view ] addSubview:dummyScrollView];
[[self view] sendSubviewToBack:dummyScrollView];
I then implement :
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
{
NSLog(#"scrollViewShouldScrollToTop");
.
.
}
Under all previous versions of IOS this has worked beautifully and flawlessly, yet under iOS 6 the scrollViewShouldScrollToTop never gets called. Is this a bug?? The API says this should still be available as part of the delegate in iOS6, yet under iOS6 on both device and simulator it never executes... Anyone have any idea what is going on?
Still no other TableView or ScrollView, but there is a MAPVIEW?? But the MapView doesn't have a shouldScrollToTop that I can find to set to NO.. so I am still beyond confused why this stopped working under iOS 6...
Is there any chance that the UIScrollView you're creating isn't somehow the only UIScrollView in your view hierarchy? It looks like in iOS6, if you have more than a single UIScrollView in your view hierarchy, only one should have scrollsToTop = YES. This is the one that'll have its scrollViewShouldScrollToTop method called.
My problem was similar in that I had a very basic UITableView that would no longer autoscroll to the top when the status bar was tapped. I finally remembered that one of the cells in my tableView uses a UIWebView, and that the cell's webView.scrollView was (correctly, now in iOS6) hijacking the call to scrollViewShouldScrollToTop that, before iOS6, was being made on my tableView.
After setting the tableViewCell's "scrollsToTop = NO", the status bar autoscroll once again worked as it did before. Here's more-or-less how the code looks:
myCustomCellWithAWebView.webView.scrollView.scrollsToTop = NO;
Hope this helps!
On iOS 6, only tap the part above scrollview of status bar can fire scrollsToTop event.
And, that scrollView can't be hidden or 0 alpha.
But it can be covered. or clear background color.
So on iOS 6, you need
dummyScrollView.frame = self.view.bounds;
dummyScrollView.backgroundColor = [UIColor clearColor];

Resources