UIImageView .scaleAspectFit 和自动布局不能从 Swift 以编程方式工作

Posted

技术标签:

【中文标题】UIImageView .scaleAspectFit 和自动布局不能从 Swift 以编程方式工作【英文标题】:UIImageView .scaleAspectFit and autolayout not working programmatically from Swift 【发布时间】:2017-05-18 06:11:00 【问题描述】:

我有几个部分透明的 PNG 叠加层可以在视图中相互叠加显示。覆盖的数量取决于运行时条件。我想在 Swift 中创建 UIImageView 实例并将它们添加到视图中。

在情节提要中添加 UIImageView 并通过 Swift 设置其图像时,我可以轻松获得我想要的行为。在这种情况下,我将 UIImageView 的前导、尾随、顶部和底部固定到父包装器 UIView 的前导、尾随、顶部和底部。在UIImageView 的属性检查器中,我将“内容模式”设置为“Aspect Fit”,当 Swift 设置图像时,大图像会很好地缩小。用户可以在 iPhone 的小屏幕上看到整个图像。

当我动态创建 UIImageView 并将其添加到同一个父包装器 UIView 时,我遇到了约束问题。有太多的约束需要满足。

我不明白为什么通过 Swift 创建的 UIImageView 与通过情节提要创建的 UIImageView 不同。

如何让通过 Swift 创建的 UIImageView 的行为与通过情节提要创建的 UIImageView 一样?

在通过故事板创建的UIImageView 和通过 Swift 创建的UIImageView 上设置图像的 Swift 代码。

override func viewDidLoad() -> Void 
    super.viewDidLoad();

    let imageFilePath: String = Bundle.main.resourceURL!.appendingPathComponent("img/a.png", isDirectory: false).path;

    // Use the outlet to set the image in the UIImageView created in the storyboard.
    // This works.

    self.storyboardImageView.image = UIImage(contentsOfFile: imageFilePath);

    // Create a UIImageView programatically and add it to the same wrapper UIView
    // that also contains the UIImageView above.
    // This doesn't work.

    let swiftImageView: UIImageView = UIImageView(image: UIImage(contentsOfFile: imageFilePath));

    // The presence of the following line makes no difference
    //
    swiftImageView.contentMode = .scaleAspectFill;

    self.storyboardWrapperView.addSubview(swiftImageView);

    swiftImageView.topAnchor.constraint(equalTo: self.storyboardWrapperView.topAnchor).isActive = true;
    swiftImageView.bottomAnchor.constraint(equalTo: self.storyboardWrapperView.bottomAnchor).isActive = true;
    swiftImageView.leadingAnchor.constraint(equalTo: self.storyboardWrapperView.leadingAnchor).isActive = true;
    swiftImageView.trailingAnchor.constraint(equalTo: self.storyboardWrapperView.trailingAnchor).isActive = true;

当布局管理器试图满足冲突约束时,我在 Xcode 中看到的输出。

2017-05-17 22:45:18.351141-0700 My App[29787:7263069] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x170096670 h=--& v=--& UIImageView:0x101432d20.midX == 540   (active)>",
    "<NSLayoutConstraint:0x174092520 H:|-(0)-[UIView:0x101439120]   (active, names: '|':UIView:0x10142f4a0 )>",
    "<NSLayoutConstraint:0x174092570 H:[UIView:0x101439120]-(0)-|   (active, names: '|':UIView:0x10142f4a0 )>",
    "<NSLayoutConstraint:0x1740936a0 H:|-(0)-[UIImageView:0x101432d20]   (active, names: '|':UIView:0x101439120 )>",
    "<NSLayoutConstraint:0x174093790 UIImageView:0x101432d20.trailing == UIView:0x101439120.trailing   (active)>",
    "<NSLayoutConstraint:0x17009b260 'UIView-Encapsulated-Layout-Width' UIView:0x10142f4a0.width == 375   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x174093790 UIImageView:0x101432d20.trailing == UIView:0x101439120.trailing   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2017-05-17 22:45:18.360996-0700 My App[29787:7263069] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<_UILayoutSupportConstraint:0x174091cb0 _UILayoutGuide:0x10143e8d0.height == 0   (active)>",
    "<_UILayoutSupportConstraint:0x174092930 V:|-(0)-[_UILayoutGuide:0x10143e8d0]   (active, names: '|':UIView:0x10142f4a0 )>",
    "<_UILayoutSupportConstraint:0x174091da0 _UILayoutGuide:0x10143ddc0.height == 0   (active)>",
    "<_UILayoutSupportConstraint:0x174091490 _UILayoutGuide:0x10143ddc0.bottom == UIView:0x10142f4a0.bottom   (active)>",
    "<NSAutoresizingMaskLayoutConstraint:0x17009cc50 h=--& v=--& UIImageView:0x101432d20.midY == 877.5   (active)>",
    "<NSLayoutConstraint:0x174092660 V:[_UILayoutGuide:0x10143e8d0]-(0)-[UIView:0x101439120]   (active)>",
    "<NSLayoutConstraint:0x1740927a0 V:[UIView:0x101439120]-(0)-[_UILayoutGuide:0x10143ddc0]   (active)>",
    "<NSLayoutConstraint:0x174093380 V:|-(0)-[UIImageView:0x101432d20]   (active, names: '|':UIView:0x101439120 )>",
    "<NSLayoutConstraint:0x174093650 UIImageView:0x101432d20.bottom == UIView:0x101439120.bottom   (active)>",
    "<NSLayoutConstraint:0x170098830 'UIView-Encapsulated-Layout-Height' UIView:0x10142f4a0.height == 667   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x174093650 UIImageView:0x101432d20.bottom == UIView:0x101439120.bottom   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

当我使用 Xcode 调试 Debug View Hierarchy 时

以下链接图片显示:

    父包装 UIView 上的约束。 通过情节提要创建的 UIImageView 上的约束。 通过 Swift 创建的 UIImageView 上的约束。

constraint values

【问题讨论】:

添加这一行swiftImageView.translatesAutoresizingMaskIntoConstraints = false 做到了!谢谢你。 :-) 【参考方案1】:

在您的控制台日志中,这两行告诉您发生了什么:

(注意:如果您看到 NSAutoresizingMaskLayoutConstraints 不明白,参考UIView属性的文档 translatesAutoresizingMaskIntoConstraints)

.

NSAutoresizingMaskLayoutConstraint:0x17009cc50 h=--& v=--& UIImageView:0x101432d20.midY == 877.5(活动)

将此行添加到您的代码将解决问题:

swiftImageView.translatesAutoresizingMaskIntoConstraints = false

【讨论】:

以上是关于UIImageView .scaleAspectFit 和自动布局不能从 Swift 以编程方式工作的主要内容,如果未能解决你的问题,请参考以下文章

使 UIImageview 根据另一个 UIImageview 旋转而旋转

UIImageview的简单运用

如何同时为 UIImageView 的图像和 UIImageView 本身设置动画?

ios UIImageView处理图片大小问题

滑动手指 UIImageView

UIImageView02