iOS 纵横比约束在 iOS 7 上中断,适用于 iOS 8
Posted
技术标签:
【中文标题】iOS 纵横比约束在 iOS 7 上中断,适用于 iOS 8【英文标题】:iOS aspect ratio constraint breaks on iOS7, works on iOS8 【发布时间】:2015-01-23 14:03:18 【问题描述】:在我的应用程序中,我设置了 UIView 的约束,其高度是使用纵横比约束从宽度计算出来的。它在 ios8 上完美运行,适用于各种设备屏幕尺寸(3.5、4、4.7、5.5),但它会导致应用在所有 iOS7 设备上崩溃。
我假设这是纵横比约束,因为如果我用固定高度约束替换它,它就不会再崩溃(显然它在某些设备上看起来很糟糕)。
堆栈跟踪非常长,所以我只是复制它的一部分。
提前感谢您的帮助!
Objective: objective 0x7f9d90da33c0: <750:4692, 251:2936, 250:367> + <251:-1>*0x7f9d90c06220.markerid: 592 + <251:-1>*0x7f9d90c24420.markerid: 599 + <251:-1>*0x7f9d90c25650.markerid: 594 + <251:-1>*0x7f9d90c27ad0.markerid: 597 + <750:-1>*0x7f9d90c3b270.markerid: 483 + <250:-3.9875>*0x7f9d90c43e40.markerid: 618 + <250:-3.9875>*0x7f9d90c43e90.markerid: 620 + <750:-4>*0x7f9d90c442e0.markerid: 479 + <251:1>*0x7f9d90c464b0.markerid: 485 + <251:-1>*0x7f9d90c46bf0.markerid: 504 + <251:-1>*0x7f9d90c46c90.markerid: 508 + <251:-1>*0x7f9d90c46ce0.markerid: 510 + <251:-1>*0x7f9d90c46d80.markerid: 514 + <251:-2>*0x7f9d90c4aa60.markerid: 623 + <251:-2>*0x7f9d90c4aab0.markerid: 625 + <251:-2, 250:-3.9875>*0x7f9d90c4ab50.markerid: 631 + <251:-2, 250:-3.9875>*0x7f9d90c4abf0.markerid: 634 + <251:4, 250:3.9875>*0x7f9d90c4ac40.markerid: 637 + <251:4, 250:3.9875>*0x7f9d90c4ac90.markerid: 642 + <750:1, 251:1>*0x7f9d90c4c530.negErrorid: 645 + <750:1, 251:1>*0x7f9d90c4cb20.posErrorMarkerid: 646 + <750:1, 251:1>*0x7f9d90c530f0.negErrorid: 649 + <750:1, 251:1>*0x7f9d90c53150.negErrorid: 651 + <750:1, 250:1>*0x7f9d90c53820.posErrorMarkerid: 652 + <750:1, 250:1>*0x7f9d90c538a0.posErrorMarkerid: 654 + <750:1, 250:1>*0x7f9d90c53fd0.posErrorMarkerid: 656 + <750:1, 250:1>*0x7f9d90c54070.posErrorMarkerid: 658 + <750:1, 251:1>*0x7f9d90c54650.negErrorid: 661 + <750:1>*0x7f9d90c546b0.negErrorid: 663 + <251:1>*0x7f9d90c546b0.posErrorMarkerid: 662 + <750:1>*0x7f9d90c55230.negErrorid: 665 + <251:1>*0x7f9d90c55230.posErrorMarkerid: 664 + <750:1, 251:1>*0x7f9d90c552b0.negErrorid: 667 + <750:1, 251:1>*0x7f9d90d34300.posErrorMarkerid: 916 + <750:1>*0x7f9d90de48a0.markerid: 738 + <250:-1>*0x7f9d90de48f0.markerid: 740 + <250:-1>*0x7f9d90de4940.markerid: 744 + <750:1>*0x7f9d90de4990.markerid: 745 + <750:1>*0x7f9d90de4c70.markerid: 718 + <750:1>*0x7f9d90de4cc0.markerid: 720 + <250:-1
...
Integralization Adjustments:
0x7f9d93042a90.markerid: 532 [<NSLayoutConstraint:0x7f9d93042a90 UIView:0x7f9d9303d590.width == 1.50943*UIView:0x7f9d9303d590.height>] -> 0.132066
0x7f9d93042c70.markerid: 546 [<NSLayoutConstraint:0x7f9d93042c70 UIButton:0x7f9d90de27a0.height == UIButton:0x7f9d93018ab0.height>] -> 1.000000
0x7f9d93042d60.markerid: 552 [<NSLayoutConstraint:0x7f9d93042d60 UIButton:0x7f9d9303dbf0.width == UIButton:0x7f9d93018ab0.width>] -> -1.000000
0x7f9d93042db0.markerid: 554 [<NSLayoutConstraint:0x7f9d93042db0 UIButton:0x7f9d9303dbf0.height == UIButton:0x7f9d93033b40.height>] -> 1.000000
0x7f9d93042ea0.markerid: 562 [<NSLayoutConstraint:0x7f9d93042ea0 UIButton:0x7f9d93033b40.width == UIButton:0x7f9d9303c500.width>] -> -1.000000
0x7f9d930431c0.markerid: 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.Heightid: 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
【问题讨论】:
有史以来最可怕的错误。 【参考方案1】:这是一个令人讨厌的错误,也花费了我很多时间。我遇到了完全相同的问题,该应用程序在 iOS 8 中运行良好,但在 iOS 7.1 中崩溃了。问题是滚动视图的纵横比约束。在尝试了很多不同的东西之后,这终于解决了这个问题:
崩溃似乎是浮点计算在某些时候失败的结果。在我的例子中,我定义了 16:9 或者更确切地说是 9:16 的纵横比,即 0.5625。 将乘数从 0.5625 更改为 0.5624 解决了问题,此后不再出现崩溃。
【讨论】:
在解决方案中大声笑:-D。无论如何,我会发疯地解决 iOS7 上的问题。 大声笑是的,它完全荒谬,但它是唯一真正修复它的东西......我尝试了这里和类似帖子中建议的所有内容,但没有任何帮助......我相信我的约束设置正确......有趣的是......切换约束的宽度和高度实际上稍微缓解了问题,应用程序似乎崩溃的频率只有一半......但没有什么期望改变乘数真的解决了它;) 您是否将每个 AP 约束的乘数更改为“固定”值?如,从 9:16 更改为 0.5624?为什么是 0.5624 而不是 0.5625,后者不起作用? 9:16 正好是 0.5625。所以我所做的就是将乘数更改为非常小的数量。我可能也可以将乘数更改为 9000:15999。崩溃的原因似乎是自动布局引擎中的一些错误导致浮点精度累积损失,可以在这篇文章中找到具有更广泛解释的类似问题:***.com/questions/17688370/…【参考方案2】:我通过以下方式解决了它:
假设我的面板在 iPhone 4、4s、5、5s 上看起来相同,因为它们具有相同的宽度,因此它们的纵横比将导致相同的高度。我在添加纵横比约束的同一个视图中添加了高度约束。因此,无论 iOS 版本如何,在这些设备上,视图都会在高度约束下正常显示。
iPhone6 和 6+ 只能在 iOS8 或更高版本上运行,其中纵横比约束不会失败,如果 iOS 版本为 8 或更高版本,我只需删除高度约束,否则我删除纵横比约束。
它远非优雅,而是以一种简单的方式解决了问题。
【讨论】:
也许您可以向 Apple 提交错误报告? (“这不应该发生”听起来像是操作系统在那里做错了什么?)【参考方案3】:我在 iOS7 上遇到了这个崩溃,当时我有纵横比、与容器相等的高度以及与容器约束的顶部和底部间距为零的组合。与容器的等高约束是多余的,因为它被约束在容器的顶部和底部,所以我将其移除并且崩溃停止了。这一定是操作系统的错误。
【讨论】:
【参考方案4】:确实,这一定是 OS (iOS 7) 的 bug。我花了几天时间调试 autolayout 完全崩溃(注意:没有 NSLayout 异常)。我也快崩溃了。
这完全是由于使用了一些约束组合和纵横比约束。
我正在通过重新设计 UI 来解决这个问题...痛苦。
【讨论】:
【参考方案5】:我解决了 您不设置比率本身。你应该设置等于它的容器 但最好你应该按照 iPhone 6 设置高度限制。 你必须在你的类中输出约束。在 viewDidLoad 中,您必须乘以 DISPLAY_SCALE
DISPLAY_SCALE = UIScreen.mainScreen().bounds.width / 375
// 375 是 iPhone 6 的宽度。
为什么你必须这样做?我认为 iOS7 在计算我们的约束时会延迟。而且显示时出错
【讨论】:
【参考方案6】:我在 iOS 7 上遇到了 NSLayoutConstraint
和乘数的问题。在 iOS 8 上完美运行。
我正在使用值为 0.2 的乘数,它会导致错误!
NSLayoutConstraint(item: BT_Facebook,
attribute: NSLayoutAttribute.Width,
relatedBy: .Equal,
toItem: nil,
attribute: .Width,
multiplier: 0.2,
constant: sizeBtRedeSociais)
解决方案是使用屏幕的大小,而不是百分比。
var sizeBtRedeSociais = UIScreen.mainScreen().bounds.width / 5
var BT_FacebookWidth = NSLayoutConstraint(item: BT_Facebook, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: nil, attribute: .Width, multiplier: 1, constant: sizeBtRedeSociais)
var BT_TwitterWidth = NSLayoutConstraint(item: BT_Twitter, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: nil, attribute: .Width, multiplier: 1, constant: sizeBtRedeSociais)
var BT_InstagramWidth = NSLayoutConstraint(item: BT_Instagram, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: nil, attribute: .Width, multiplier: 1, constant: sizeBtRedeSociais)
var BT_GoogleWidth = NSLayoutConstraint(item: BT_Google, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: nil, attribute: .Width, multiplier: 1, constant: sizeBtRedeSociais)
var BT_YoutubeWidth = NSLayoutConstraint(item: BT_Youtube, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: nil, attribute: .Width, multiplier: 1, constant: sizeBtRedeSociais)
【讨论】:
以上是关于iOS 纵横比约束在 iOS 7 上中断,适用于 iOS 8的主要内容,如果未能解决你的问题,请参考以下文章
iOS 8 UITableViewCell 与 UIImageView 动态高度