MKMapView struggles with zero height constraint - edgeInsets of map view?

五迷三道 提交于 2021-02-09 17:59:06

问题


I have an MKMapView about 300 high which collapses between two other views, simply animating the height up and down as you'd usually do when collapsing a view.

@IBOutlet var heightMap: NSLayoutConstraint!
@IBOutlet var theMap: MKMapView!

When the view launches it is height zero..

override func viewDidLoad() {
    super.viewDidLoad()
    ..
    heightMap.constant = 0
}

there's an infuriating warning...

[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. 
(
    "<NSLayoutConstraint:0x6080000904f0 MKMapView:0x7fe6b3000600.height == 0   (active)>",
    "<NSLayoutConstraint:0x608000093a60 UILayoutGuide:0x60800018fd80'Edge Insets'.top == MKMapView:0x7fe6b3000600.top + 8   (active)>",
    "<NSLayoutConstraint:0x608000093b50 UILayoutGuide:0x60800018fd80'Edge Insets'.bottom == MKMapView:0x7fe6b3000600.bottom   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x608000093b50 UILayoutGuide:0x60800018fd80'Edge Insets'.bottom == MKMapView:0x7fe6b3000600.bottom   (active)>

Note that it seems to be struggling with "edgeInsets" or possibly "Edge Insets" (with a space!) top and bottom,

'Edge Insets'.top == MKMapView:0x7fe6b3000600.top + 8
'Edge Insets'.bottom == MKMapView:0x7fe6b3000600.bottom

Map views have a read-only property .alignmentRectInsets

(Actually when I print that out, whatever it is, it is zero anyway..

let ari = theMap.alignmentRectInsets
print("wth \(ari)")
> wth UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)

)

I can't even find any info about "edge insets" on a MKMapView, what's the deal here?

I've carefully checked for not-installed constraints and the usual problems.


回答1:


Interestingly I only get this error if the initial hieght is zero, so it seems to be an issue with the initial setup of the mapview. The solution them seems to be to be

  1. Give the mapView a hieght in the storyboard (I did 100)
  2. Make the mapView hidden by checking the hidden box in interface builder

When its time to show the mapView:

  1. Unhide it
  2. Minimize it (I set the constant to .ulpOfOne instead of zero because technically frames are not supposed to be degenerate.)
  3. Animate to the final position

    class ViewController: UIViewController{
        @IBOutlet weak var m: MKMapView!
        @IBOutlet weak var h: NSLayoutConstraint!
        @IBAction func t(_ sender: Any) {
            m.isHidden = false
            h.constant = .ulpOfOne
            view.layoutIfNeeded()
            h.constant = 100
            UIView.animate(withDuration: 3) {
                self.view.layoutIfNeeded()
            }
        }
    }
    

FYI I would actually use a UIStackView for this and just animate isHidden instead and then you don't even have to deal with the constraint in code.




回答2:


I've struggled with the same issue and got this warning every time I wanted to hide a MKMapView (either manually with a height constraint or inside a UIStackView). I've noticed that I can prevent the warning by setting the map view's bounds height to 0 before activating the zero height constraint. So I wrote a little class to encapsulate the bug:

import MapKit

class HideableMapView: MKMapView {

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

        if self.containsZeroHeightConstraint() {
            // Set the bounds manually before the constraint gets processed to prevent an auto layout warning
            self.bounds.size.height = 0
        }

        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
    }

    private func containsZeroHeightConstraint() -> Bool {
        return (self.constraints.filter { $0.firstAttribute == .height && $0.constant == 0 }).isEmpty == false
    }
}

This class worked for my project where MKMapView is embedded in a UIStackView. Depending on your setup you may have to override another method. Set a symbolic breakpoint for UIViewAlertForUnsatisfiableConstraints to view the call stack.

I've also filed a radar, which you can find here: https://openradar.appspot.com/radar?id=6109127172423680



来源:https://stackoverflow.com/questions/43322973/mkmapview-struggles-with-zero-height-constraint-edgeinsets-of-map-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!