Programmatic Constraints Problem

#1

At the end of the programmatic constraints section I run the program and get a strange error that I wasn’t getting before. My entire program crashes when I click on the maps.

here is the stack trace ===>

ConversionViewController loaded its view.
2016-03-27 00:00:17.947 WorldTrotter[8664:660372] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with items <UISegmentedControl: 0x7fc099fef810; frame = (0 0; 212 29); opaque = NO; layer = <CALayer: 0x7fc09cb8aa10>> and <MKMapView: 0x7fc099c0a740; frame = (0 0; 0 0); clipsToBounds = YES; layer = <CALayer: 0x7fc099c0aac0>> because they have no common ancestor.  Does the constraint reference items in different view hierarchies?  That's illegal.'
*** First throw call stack:
(
	0   CoreFoundation                      0x0000000106cb0d85 __exceptionPreprocess + 165
	1   libobjc.A.dylib                     0x0000000108a54deb objc_exception_throw + 48
	2   CoreFoundation                      0x0000000106cb0cbd +[NSException raise:format:] + 205
	3   WorldTrotter                        0x00000001067efb10 _TFC12WorldTrotter17MapViewController8loadViewfT_T_ + 2048
	4   WorldTrotter                        0x00000001067efdd2 _TToFC12WorldTrotter17MapViewController8loadViewfT_T_ + 34
	5   UIKit                               0x0000000107673560 -[UIViewController loadViewIfRequired] + 138
	6   UIKit                               0x0000000107673cd3 -[UIViewController view] + 27
	7   UIKit                               0x00000001076d71bc -[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:] + 502
	8   UIKit                               0x00000001076d6130 -[UITabBarController transitionFromViewController:toViewController:] + 59
	9   UIKit                               0x00000001076d1f41 -[UITabBarController _setSelectedViewController:] + 377
	10  UIKit                               0x00000001076d1db7 -[UITabBarController setSelectedViewController:] + 234
	11  UIKit                               0x00000001076d5fa1 -[UITabBarController _tabBarItemClicked:] + 481
	12  UIKit                               0x00000001074daa8d -[UIApplication sendAction:to:from:forEvent:] + 92
	13  UIKit                               0x00000001078b8066 -[UITabBar _sendAction:withEvent:] + 498
	14  UIKit                               0x00000001074daa8d -[UIApplication sendAction:to:from:forEvent:] + 92
	15  UIKit                               0x000000010764de67 -[UIControl sendAction:to:forEvent:] + 67
	16  UIKit                               0x000000010764e143 -[UIControl _sendActionsForEvents:withEvent:] + 327
	17  UIKit                               0x00000001078bd1bb -[UITabBar(Static) _buttonUp:] + 103
	18  UIKit                               0x00000001074daa8d -[UIApplication sendAction:to:from:forEvent:] + 92
	19  UIKit                               0x000000010764de67 -[UIControl sendAction:to:forEvent:] + 67
	20  UIKit                               0x000000010764e143 -[UIControl _sendActionsForEvents:withEvent:] + 327
	21  UIKit                               0x000000010764d263 -[UIControl touchesEnded:withEvent:] + 601
	22  UIKit                               0x000000010754d99f -[UIWindow _sendTouchesForEvent:] + 835
	23  UIKit                               0x000000010754e6d4 -[UIWindow sendEvent:] + 865
	24  UIKit                               0x00000001074f9dc6 -[UIApplication sendEvent:] + 263
	25  UIKit                               0x00000001074d3553 _UIApplicationHandleEventQueue + 6660
	26  CoreFoundation                      0x0000000106bd6301 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
	27  CoreFoundation                      0x0000000106bcc22c __CFRunLoopDoSources0 + 556
	28  CoreFoundation                      0x0000000106bcb6e3 __CFRunLoopRun + 867
	29  CoreFoundation                      0x0000000106bcb0f8 CFRunLoopRunSpecific + 488
	30  GraphicsServices                    0x000000010ba97ad2 GSEventRunModal + 161
	31  UIKit                               0x00000001074d8f09 UIApplicationMain + 171
	32  WorldTrotter                        0x00000001067f0e02 main + 114
	33  libdyld.dylib                       0x000000010c37a92d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Here is the offending code:

override func loadView() {
        // Create a map view
        mapView = MKMapView()
    
        // Set it as *the* view of this view controller
        view = mapView
        
        let segmentedControl = UISegmentedControl(items: ["Standard", "Hybrid", "Satellite"])
        
        segmentedControl.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.5)
        
        segmentedControl.selectedSegmentIndex = 0
        
        segmentedControl.translatesAutoresizingMaskIntoConstraints = false
        
        let topConstraint = segmentedControl.topAnchor.constraintEqualToAnchor(view.topAnchor)
        
        let leadingConstraint = segmentedControl.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor)
        
        let trailingConstraint = segmentedControl.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor)
        
        topConstraint.active = true
        leadingConstraint.active = true
        trailingConstraint.active = true
        
        view.addSubview(segmentedControl)
    }
#2

When your code adds the constraints, your segmented control is floating in space somewhere. You have to add the segmented control to the map view before adding constraints between the map view and and the segmented control–i.e. in order to constrain elements to each other they have to be part of the same view hierarchy.

1 Like
#3

Thanks so much for this. That really helped me out. I see I need to add the view.addSubview(segmentedControl) in the right spot before the creation of the top constraint. I didn’t realize there was a specific order they had to be in. :smiley:

I guess what I am getting at is segmentedControl in this case is some type of instance of a class UISegmentedControl therefore when added to the view as a subview I still actually have a reference to it and that allows me to add the constraints to it after its already placed in in the view.