Our DNA is written in Swift
Jump

Radar: Incorrect Horizontal Size Class

I found this bug while working on an app for our ProductLayer startup. There is a new segue “Present as Popover” which dynamically decides to present a view controller either modally full screen or as popover depending on the available screen width. On iPhone 6+ this shows as popover in landscape orientation and modally in portrait. On iPads it always shows as popover.

Filed as rdar://18893122 and on Open Radar.

Ad

This problem becomes apparent if you want to hide a navigation bar – with a Done button – which is not necessary in a popover since those can be dismissed by tapping outside the bubble. To do that you have to inspect the horizontal size class value of the view controller’s traitCollection. This should always be Regular in landscape and Compact in portrait orientation (on iPhone 6+). The bug is that if you perform this segue with the iPhone 6+ already in landscape then you get an incorrect Compact horizontal size class report.

Here is how it should look: The navigation bar gets hidden because the horizontal size class gets correctly reported as Regular.

Size Class Ok

 

But if you perform the segue with iPhone 6+ in landscape orientation the horizontal size class is reported as Compact and thus we don’t know that we should hide the navigation bar.

Size Class Error

 

I am mentioning a nasty workaround for this problem at the end of this article.

Incorrect Horizontal Size class with “present as popover” on iPhone 6+

Summary

The segue style “Present as Popover” presents a view controller as modal full-screen or in a popover size permitting. This occurs on iPhone 6+ in landscape orientation and on iPad all the time.

If an iPhone 6+ is rotated to landscape and then this segue executed the presented VC gets an incorrect horizontal size class of Compact in the traitCollection. Only when you rotate the device to portrait and back to landscape this gets corrected to Regular.

This is a problem for the use case when you want to hide a navigation bar every time the VC is presented as a popover since you can dismiss the popover by tapping outside of it and don’t need a Close button.

Steps to Reproduce

  1. Launch the provided sample app on iPhone 6+ (sim or device).
  2. In Portrait tap on the Segue button. Note that the horizontal size class is Compact.
  3. Rotate to landscape. Note that the second VC now gets presented as popover. Horizontal size class is now Regular.
  4. The nav bar is now hidden, dismiss the bubble by tapping outside.
  5. In Landscape, tap on the Segue button. Note that the horizontal size class is now INCORRECTLY Compact.

Expected Results

  • The horizontal size class should be Regular when presented in a popover

Actual Results

  • The horizontal size class is Compact when presented with the iPhone 6+ in landscape
  • The horizontal size class changes to Regular through rotating the device to portrait and then to landscape again

Notes

The sample app is the SizeClassBug project in my RadarSamples github repository. A workaround for this faulty behaviour can be achieved by manually correcting the horizontal size class:

- (void)viewWillAppear:(BOOL)animated
{
   [super viewWillAppear:animated];
 
   // workaround for iPhone 6+ bug
   if (self.traitCollection.displayScale==3)
   {
      CGSize windowSize = [UIScreen mainScreen].bounds.size;
      CGSize viewSize = self.view.bounds.size;
 
      if (viewSize.width < windowSize.width)
      {
         UITraitCollection *collection = [UITraitCollection
            traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular];
         [self _setupForTraitCollection:collection];
         return;
      }
   }
 
   [self _setupForTraitCollection:self.traitCollection];
}
 
- (void)_setupForTraitCollection:(UITraitCollection *)collection
{
   if (collection.horizontalSizeClass == UIUserInterfaceSizeClassRegular ||
       collection.userInterfaceIdiom == UIUserInterfaceIdiomPad)
   {
      [self.navigationController setNavigationBarHidden:YES];
   }
   else
   {
      [self.navigationController setNavigationBarHidden:NO];
   }
}
 
- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection
              withTransitionCoordinator:(id)coordinator
{
   [self _setupForTraitCollection:newCollection];
}

Categories: Bug Reports

1 Comment »

Trackbacks

  1. iPhone Downsizing | Cocoanetics

Leave a Comment

%d bloggers like this: