Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS aspect ratio constraint breaks on iOS7, works on iOS8

Tags:

ios

autolayout

In my app, I have setup a UIView's constraints in a way where its height gets calculated from its width using the aspect ratio constraint. It works perfectly on iOS8 with every device screen size (3.5, 4, 4.7, 5.5), but it causes the app to crash on every iOS7 device.

I assume it's the aspect ratio constraint, because if I replace it with a fixed height constraint, it doesn't crash anymore (obviously it looks bad on some devices).

The stack trace is extremely long, so I'm only copying parts of it.

Thank you in advance for your help!

Objective: {objective 0x7f9d90da33c0: <750:4692, 251:2936, 250:367> + <251:-1>*0x7f9d90c06220.marker{id: 592} + <251:-1>*0x7f9d90c24420.marker{id: 599} + <251:-1>*0x7f9d90c25650.marker{id: 594} + <251:-1>*0x7f9d90c27ad0.marker{id: 597} + <750:-1>*0x7f9d90c3b270.marker{id: 483} + <250:-3.9875>*0x7f9d90c43e40.marker{id: 618} + <250:-3.9875>*0x7f9d90c43e90.marker{id: 620} + <750:-4>*0x7f9d90c442e0.marker{id: 479} + <251:1>*0x7f9d90c464b0.marker{id: 485} + <251:-1>*0x7f9d90c46bf0.marker{id: 504} + <251:-1>*0x7f9d90c46c90.marker{id: 508} + <251:-1>*0x7f9d90c46ce0.marker{id: 510} + <251:-1>*0x7f9d90c46d80.marker{id: 514} + <251:-2>*0x7f9d90c4aa60.marker{id: 623} + <251:-2>*0x7f9d90c4aab0.marker{id: 625} + <251:-2, 250:-3.9875>*0x7f9d90c4ab50.marker{id: 631} + <251:-2, 250:-3.9875>*0x7f9d90c4abf0.marker{id: 634} + <251:4, 250:3.9875>*0x7f9d90c4ac40.marker{id: 637} + <251:4, 250:3.9875>*0x7f9d90c4ac90.marker{id: 642} + <750:1, 251:1>*0x7f9d90c4c530.negError{id: 645} + <750:1, 251:1>*0x7f9d90c4cb20.posErrorMarker{id: 646} + <750:1, 251:1>*0x7f9d90c530f0.negError{id: 649} + <750:1, 251:1>*0x7f9d90c53150.negError{id: 651} + <750:1, 250:1>*0x7f9d90c53820.posErrorMarker{id: 652} + <750:1, 250:1>*0x7f9d90c538a0.posErrorMarker{id: 654} + <750:1, 250:1>*0x7f9d90c53fd0.posErrorMarker{id: 656} + <750:1, 250:1>*0x7f9d90c54070.posErrorMarker{id: 658} + <750:1, 251:1>*0x7f9d90c54650.negError{id: 661} + <750:1>*0x7f9d90c546b0.negError{id: 663} + <251:1>*0x7f9d90c546b0.posErrorMarker{id: 662} + <750:1>*0x7f9d90c55230.negError{id: 665} + <251:1>*0x7f9d90c55230.posErrorMarker{id: 664} + <750:1, 251:1>*0x7f9d90c552b0.negError{id: 667} + <750:1, 251:1>*0x7f9d90d34300.posErrorMarker{id: 916} + <750:1>*0x7f9d90de48a0.marker{id: 738} + <250:-1>*0x7f9d90de48f0.marker{id: 740} + <250:-1>*0x7f9d90de4940.marker{id: 744} + <750:1>*0x7f9d90de4990.marker{id: 745} + <750:1>*0x7f9d90de4c70.marker{id: 718} + <750:1>*0x7f9d90de4cc0.marker{id: 720} + <250:-1

...

 Integralization Adjustments:
0x7f9d93042a90.marker{id: 532} [<NSLayoutConstraint:0x7f9d93042a90 UIView:0x7f9d9303d590.width == 1.50943*UIView:0x7f9d9303d590.height>] -> 0.132066
0x7f9d93042c70.marker{id: 546} [<NSLayoutConstraint:0x7f9d93042c70 UIButton:0x7f9d90de27a0.height == UIButton:0x7f9d93018ab0.height>] -> 1.000000
0x7f9d93042d60.marker{id: 552} [<NSLayoutConstraint:0x7f9d93042d60 UIButton:0x7f9d9303dbf0.width == UIButton:0x7f9d93018ab0.width>] -> -1.000000
0x7f9d93042db0.marker{id: 554} [<NSLayoutConstraint:0x7f9d93042db0 UIButton:0x7f9d9303dbf0.height == UIButton:0x7f9d93033b40.height>] -> 1.000000
0x7f9d93042ea0.marker{id: 562} [<NSLayoutConstraint:0x7f9d93042ea0 UIButton:0x7f9d93033b40.width == UIButton:0x7f9d9303c500.width>] -> -1.000000
0x7f9d930431c0.marker{id: 581} [<NSLayoutConstraint:0x7f9d930431c0 UIButton:0x7f9d9303c500.height == UIButton:0x7f9d93045880.height>] -> 1.000000

  Statistics:
    195 rows. Variable counts:
          1 ->  59
          2 ->  28
          3 ->   3
          4 ->   7
          5 ->   4
          6 ->   3
          7 ->   3
          8 ->   4
          9 ->   8
         10 ->  10
         11 ->  11
         12 ->  10
         13 ->   7
         14 ->   2
         15 ->   3
         16 ->  10
         17 ->  17
         18 ->   6
}: internal error.  Cannot find an outgoing row head for incoming head UIView:0x7f9d930332a0.Height{id: 981}, which should never happen.'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000011284d495 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000011220699e objc_exception_throw + 43
    2   CoreFoundation                      0x000000011284d2ad +[NSException raise:format:] + 205
    3   Foundation                          0x0000000110dfb054 -[NSISEngine minimizeConstantInObjectiveRowWithHead:] + 178
    4   Foundation                          0x0000000110dfaf22 -[NSISEngine optimize] + 147
    5   Foundation                          0x0000000110f432e3 -[NSISEngine withBehaviors:performModifications:] + 192
    6   UIKit                               0x000000011126f889 -[UIView(Hierarchy) _postMovedFromSuperview:] + 321
    7   UIKit                               0x000000011126df42 __UIViewWasRemovedFromSuperview + 206
    8   UIKit                               0x000000011126db9e -[UIView(Hierarchy) removeFromSuperview] + 218
    9   UIKit                               0x0000000111330069 -[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:] + 320
    10  UIKit                               0x0000000111328fdd __49-[UINavigationController _startCustomTransition:]_block_invoke + 138
    11  UIKit                               0x000000011187ec2a -[_UIViewControllerTransitionContext completeTransition:] + 78
    12  UIKit                               0x0000000111211da4 __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke103 + 605
    13  UIKit                               0x00000001112746e8 -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 299
    14  UIKit                               0x000000011126068e -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 235
    15  UIKit                               0x0000000111260941 -[UIViewAnimationState animationDidStop:finished:] + 78
    16  UIKit                               0x000000011ef6d4b7 -[UIViewAnimationStateAccessibility(SafeCategory) animationDidStop:finished:] + 48
    17  QuartzCore                          0x0000000110ac9134 _ZN2CA5Layer23run_animation_callbacksEPv + 310
    18  libdispatch.dylib                   0x000000011327772d _dispatch_client_callout + 8
    19  libdispatch.dylib                   0x00000001132673fc _dispatch_main_queue_callback_4CF + 354
    20  CoreFoundation                      0x00000001128ab289 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    21  CoreFoundation                      0x00000001127f8854 __CFRunLoopRun + 1764
    22  CoreFoundation                      0x00000001127f7d83 CFRunLoopRunSpecific + 467
    23  GraphicsServices                    0x0000000114223f04 GSEventRunModal + 161
    24  UIKit                               0x000000011121be33 UIApplicationMain + 1010
    25  Playchat                            0x000000010fa89513 main + 115
    26  libdyld.dylib                       0x00000001134fa5c9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
like image 329
Zoltan Varadi Avatar asked Jan 23 '15 14:01

Zoltan Varadi


2 Answers

This is one annoying bug, cost me a lot of hours as well. I had the exact same problem, the app was working fine in iOS 8 but crashed in iOS 7.1. The problem was an aspect ratio constraint on a scroll view. After trying out a lot of different things, this finally solved the problem:

The crash seems to be the result of a floating point calculation that fails at some point. In my case, I had defined an aspect ratio of 16:9 or rather 9:16, which amounts to 0.5625. Changing the multiplier from 0.5625 to 0.5624 fixed the problem, no more crashes have appeared since then.

like image 56
cr4sh_override Avatar answered Oct 27 '22 01:10

cr4sh_override


I resolved it in the following way:

Assuming my panel will look the same on iPhone 4, 4s, 5, 5s since they have the same width, so their aspect ratio will result in the same height. I added a height constraint to the same view that I added the aspect ratio constraint to. So regardless of the iOS version, on these devices, the view will look right with the height constraint.

iPhone6 and 6+ only run on iOS8 or higher, where the aspect ratio constraint doesn't fail, I simply delete the height constraint if the iOS version is 8 or higher, else I delete the aspect ratio constraint.

It's far from being elegant, but solves the issue in an easy way.

like image 23
Zoltan Varadi Avatar answered Oct 27 '22 00:10

Zoltan Varadi