以编程方式向 Swift 中的视图添加约束时出错
Posted
技术标签:
【中文标题】以编程方式向 Swift 中的视图添加约束时出错【英文标题】:Error when programatically adding constraints to views in Swift 【发布时间】:2016-07-29 13:05:38 【问题描述】:我在日志中收到错误,告诉我在 Swift 中以编程方式向视图添加约束时无法同时满足冲突的约束,但 UI 在运行模拟器时看起来符合我的预期您可以在屏幕截图中看到。左侧按钮的前缘与分段控件的前缘对齐,右侧按钮的后缘与分段控件的后缘对齐。
我相信是这些约束导致了问题,因为注释掉这 2 个是阻止错误被抛出的原因,但是 UI 看起来不像我想要的那样。
有人可以帮我理解我做错了什么吗?
Conversion View Controller loaded
2016-07-29 22:51:34.555 WorldTrotter[800:41503] 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.
(
"<NSLayoutConstraint:0x7fd836313550 UIButton:0x7fd836312e60'Current Location'.left == UILayoutGuide:0x7fd83630fc20'UIViewLayoutMarginsGuide'.left>",
"<NSLayoutConstraint:0x7fd836313660 UIButton:0x7fd836312e60'Current Location'.trailing == UILayoutGuide:0x7fd83630fc20'UIViewLayoutMarginsGuide'.centerX - 8>",
"<NSLayoutConstraint:0x7fd836318800 'UIView-Encapsulated-Layout-Width' H:[MKMapView:0x7fd83351d900(0)]>",
"<NSLayoutConstraint:0x7fd836312e00 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x7fd83630fc20'UIViewLayoutMarginsGuide'](LTR) (Names: '|':MKMapView:0x7fd83351d900 )>",
"<NSLayoutConstraint:0x7fd833794d30 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x7fd83630fc20'UIViewLayoutMarginsGuide']-(0)-|(LTR) (Names: '|':MKMapView:0x7fd83351d900 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7fd836313660 UIButton:0x7fd836312e60'Current Location'.trailing == UILayoutGuide:0x7fd83630fc20'UIViewLayoutMarginsGuide'.centerX - 8>
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.
2016-07-29 22:51:34.556 WorldTrotter[800:41503] 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.
(
"<NSLayoutConstraint:0x7fd836313ee0 UIButton:0x7fd8363136b0'Next Pin'.leading == UILayoutGuide:0x7fd83630fc20'UIViewLayoutMarginsGuide'.centerX + 8>",
"<NSLayoutConstraint:0x7fd836313fb0 UIButton:0x7fd8363136b0'Next Pin'.trailing == UILayoutGuide:0x7fd83630fc20'UIViewLayoutMarginsGuide'.trailing>",
"<NSLayoutConstraint:0x7fd836318800 'UIView-Encapsulated-Layout-Width' H:[MKMapView:0x7fd83351d900(0)]>",
"<NSLayoutConstraint:0x7fd836312e00 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x7fd83630fc20'UIViewLayoutMarginsGuide'](LTR) (Names: '|':MKMapView:0x7fd83351d900 )>",
"<NSLayoutConstraint:0x7fd833794d30 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x7fd83630fc20'UIViewLayoutMarginsGuide']-(0)-|(LTR) (Names: '|':MKMapView:0x7fd83351d900 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7fd836313fb0 UIButton:0x7fd8363136b0'Next Pin'.trailing == UILayoutGuide:0x7fd83630fc20'UIViewLayoutMarginsGuide'.trailing>
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.
import UIKit
import MapKit
class MapViewController: UIViewController, MKMapViewDelegate
var mapView: MKMapView!
let locationManager = CLLocationManager()
var coordinates: [CLLocationCoordinate2D] = []
var counter: Int = 0
override func loadView()
mapView = MKMapView()
mapView.delegate = self
view = mapView
//Adding pins to map
let firstLocation = CLLocationCoordinate2DMake(5.000000, -5.000000)
let secondLocation = CLLocationCoordinate2DMake(-5.000000, 5.000000)
coordinates.append(firstLocation)
coordinates.append(secondLocation)
let segmentedControl = UISegmentedControl(items: ["Standard", "Hybrid", "Satellite"])
segmentedControl.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.5)
segmentedControl.selectedSegmentIndex = 0
segmentedControl.translatesAutoresizingMaskIntoConstraints = false
segmentedControl.addTarget(self, action: #selector(MapViewController.mapTypeChanged(_:)), forControlEvents: .ValueChanged)
view.addSubview(segmentedControl)
let margins = view.layoutMarginsGuide
let topConstraint = segmentedControl.topAnchor.constraintEqualToAnchor(topLayoutGuide.bottomAnchor, constant: 8)
let leadingConstraint = segmentedControl.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor)
let trailingConstraint = segmentedControl.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor)
topConstraint.active = true
leadingConstraint.active = true
trailingConstraint.active = true
let userButton = UIButton()
view.addSubview(userButton)
userButton.translatesAutoresizingMaskIntoConstraints = false
userButton.addTarget(self, action: #selector(MapViewController.userButtonSelected(_:)), forControlEvents: UIControlEvents.TouchUpInside)
userButton.setTitle("Current Location", forState: .Normal)
userButton.backgroundColor = UIColor.blueColor().colorWithAlphaComponent(0.7)
let bTopConstraint = userButton.topAnchor.constraintEqualToAnchor(segmentedControl.bottomAnchor, constant: 8)
//Problematic constraint I think
let bLConstraint = userButton.leftAnchor.constraintEqualToAnchor(margins.leftAnchor)
let bTConstraint = userButton.trailingAnchor.constraintEqualToAnchor(margins.centerXAnchor, constant: -8)
bTopConstraint.active = true
bLConstraint.active = true
bTConstraint.active = true
let pinsButton = UIButton()
view.addSubview(pinsButton)
pinsButton.translatesAutoresizingMaskIntoConstraints = false
pinsButton.addTarget(self, action: #selector(MapViewController.pinsButtonSelected(_:)), forControlEvents: UIControlEvents.TouchUpInside)
pinsButton.setTitle("Next Pin", forState: .Normal)
pinsButton.backgroundColor = UIColor.blueColor().colorWithAlphaComponent(0.7)
let pTopConstraint = pinsButton.topAnchor.constraintEqualToAnchor(segmentedControl.bottomAnchor, constant: 8)
//Problematic constraint I think
let pLConstraint = pinsButton.leadingAnchor.constraintEqualToAnchor(margins.centerXAnchor, constant: 8)
let pTConstraint = pinsButton.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor)
pTopConstraint.active = true
pLConstraint.active = true
pTConstraint.active = true
func mapTypeChanged(segControl: UISegmentedControl)
switch segControl.selectedSegmentIndex
case 0:
mapView.mapType = .Standard
case 1:
mapView.mapType = .Hybrid
case 2:
mapView.mapType = .Satellite
default:
break
override func viewDidLoad()
super.viewDidLoad()
func userButtonSelected(button: UIButton)
if mapView.showsUserLocation == false
mapView.showsUserLocation = true
else
mapView.showsUserLocation = false
func pinsButtonSelected(button: UIButton)
if counter >= coordinates.count
counter = 0
let dropPin = MKPointAnnotation()
dropPin.coordinate = coordinates[counter]
counter += 1
mapView.addAnnotation(dropPin)
mapView.setCenterCoordinate(dropPin.coordinate, animated: false)
func mapViewWillStartLocatingUser(mapView: MKMapView)
// Ask for Authorisation from the User.
self.locationManager.requestAlwaysAuthorization()
// For use in foreground
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled()
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
mapView.setUserTrackingMode(MKUserTrackingMode.Follow, animated: true)
print("Tracking user")
【问题讨论】:
错误消息应该包含有关该问题的更多详细信息。也发布错误。 我在这段代码中看不到任何问题。 (我只是在本地运行它,它没有错误)。可能与其他部分有关。你有没有在故事板或代码的其他部分做任何事情,特别是与 MapView 相关的布局。 不是你的问题的原因,只是一个说明,你应该为你的 userButton 使用前导约束而不是左约束 是的,我真的很想看看这里可能出了什么问题。可能是 XCode 中的错误?我对情节提要中的 MapView 没有任何限制,所有内容都已以编程方式添加。我最初是领先的,但改为向左看错误是否会消失。在发布问题之前忘记改回来。我已经添加了整个 ViewController 以查看其他地方是否存在可能导致此问题的问题,但我认为没有。谢谢:) 【参考方案1】:您的问题来自您没有给您的MKMapView
一个正确的frame
。当你像这样创建它时:
mapView = MKMapView()
您将框架设置为0
宽度和0
高度。然后,自动布局将该框架转换为视图宽度和高度的约束。
列出的冲突约束之一是:
<NSLayoutConstraint:0x7fd836318800 'UIView-Encapsulated-Layout-Width' H:[MKMapView:0x7fd83351d900(0)]>
[MKMapView:0x7fd83351d900(0)]
中的0
表示MKMapView
的宽度是0
有一个约束,这当然不是你想要的。
您可以通过在创建地图视图时为其提供适当的框架来解决此问题:
替换:
mapView = MKMapView()
与:
mapView = MKMapView(frame: UIScreen.mainScreen().bounds)
我下面的答案通过让 ios 正确设置视图来解决这个问题。
上一个答案
我最初无法重现您的问题,但是当我将您的 viewController 放入 UITabBarController
时,我也看到了 Auto Layout 错误消息。
为了让它发挥作用,我在 Storyboard 中使用了标准的 UIViewController
,并将您的 loadView
代码移至 viewDidLoad
。我将MKMapView
添加为self.view
的子视图以及适当的约束,使其与self.view
的大小相同:
override func viewDidLoad()
super.viewDidLoad()
mapView = MKMapView()
mapView.delegate = self
mapView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(mapView)
NSLayoutConstraint.activateConstraints([
mapView.topAnchor.constraintEqualToAnchor(view.topAnchor),
mapView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor),
mapView.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor),
mapView.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor)
])
//Adding pins to map
let firstLocation = CLLocationCoordinate2DMake(5.000000, -5.000000)
let secondLocation = CLLocationCoordinate2DMake(-5.000000, 5.000000)
coordinates.append(firstLocation)
coordinates.append(secondLocation)
let segmentedControl = UISegmentedControl(items: ["Standard", "Hybrid", "Satellite"])
segmentedControl.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.5)
segmentedControl.selectedSegmentIndex = 0
segmentedControl.translatesAutoresizingMaskIntoConstraints = false
segmentedControl.addTarget(self, action: #selector(MapViewController.mapTypeChanged(_:)), forControlEvents: .ValueChanged)
view.addSubview(segmentedControl)
let margins = view.layoutMarginsGuide
let topConstraint = segmentedControl.topAnchor.constraintEqualToAnchor(topLayoutGuide.bottomAnchor, constant: 8)
let leadingConstraint = segmentedControl.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor)
let trailingConstraint = segmentedControl.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor)
topConstraint.active = true
leadingConstraint.active = true
trailingConstraint.active = true
let userButton = UIButton()
view.addSubview(userButton)
userButton.translatesAutoresizingMaskIntoConstraints = false
userButton.addTarget(self, action: #selector(MapViewController.userButtonSelected(_:)), forControlEvents: UIControlEvents.TouchUpInside)
userButton.setTitle("Current Location", forState: .Normal)
userButton.backgroundColor = UIColor.blueColor().colorWithAlphaComponent(0.7)
let bTopConstraint = userButton.topAnchor.constraintEqualToAnchor(segmentedControl.bottomAnchor, constant: 8)
//Problematic constraint I think
let bLConstraint = userButton.leftAnchor.constraintEqualToAnchor(margins.leftAnchor)
let bTConstraint = userButton.trailingAnchor.constraintEqualToAnchor(margins.centerXAnchor, constant: -8)
bTopConstraint.active = true
bLConstraint.active = true
bTConstraint.active = true
let pinsButton = UIButton()
view.addSubview(pinsButton)
pinsButton.translatesAutoresizingMaskIntoConstraints = false
pinsButton.addTarget(self, action: #selector(MapViewController.pinsButtonSelected(_:)), forControlEvents: UIControlEvents.TouchUpInside)
pinsButton.setTitle("Next Pin", forState: .Normal)
pinsButton.backgroundColor = UIColor.blueColor().colorWithAlphaComponent(0.7)
let pTopConstraint = pinsButton.topAnchor.constraintEqualToAnchor(segmentedControl.bottomAnchor, constant: 8)
//Problematic constraint I think
let pLConstraint = pinsButton.leadingAnchor.constraintEqualToAnchor(margins.centerXAnchor, constant: 8)
let pTConstraint = pinsButton.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor)
pTopConstraint.active = true
pLConstraint.active = true
pTConstraint.active = true
替代解决方案:
将您的 loadView
代码移动到 viewDidLoad
并删除这些行:
mapView = MKMapView()
view = mapView
在故事板中,将ViewController
中view
的类更改为MKMapView
。
将mapView
设为@IBOutlet
:
@IBOutlet var mapView: MKMapView!
在故事板中连接插座。
设置MKMapView
委托。 Control-从Storyboard中的mapView
拖动到viewController
顶部的ViewController图标并选择delegate em> 从弹出窗口中。你也可以通过调用来连接代理:
mapView.delegate = self
在viewDidLoad
.
【讨论】:
@sineil,你尝试过这些建议吗?他们对你有用吗? 我没有尝试过这些建议 - 我特别想了解为什么我会遇到错误而不是修复它们,因为这只是为了在阅读书籍时进行练习。非常感谢您花时间回复 谢谢!正是我想要的。以上是关于以编程方式向 Swift 中的视图添加约束时出错的主要内容,如果未能解决你的问题,请参考以下文章
未能尝试在 SWIFT 中以编程方式在滚动视图中添加 UIView 约束
如何向放置在 UIStackView 中的以编程方式创建的 UIButton 添加约束
Swift - StackView 和添加约束,以编程方式添加视图到堆栈 - 加载后调整单元格高度?