3

I'am trying to make the inserted view to fill the container view in which it is inserted, however iam getting

Invalid parameter not satisfying: [constraint isKindOfClass:[NSLayoutConstraint class]]

- (void)insertedView:(NSView *)insertedView needsToFillContainerView:(NSView *)containerView {

    [containerView addSubview:insertedView];
    [containerView setTranslatesAutoresizingMaskIntoConstraints:NO];

    [containerView addConstraints:@[
                                    [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[insertedView]|"
                                                                            options:0
                                                                            metrics:nil
                                                                              views:NSDictionaryOfVariableBindings(insertedView)],
                                    [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[insertedView]|"
                                                                            options:0
                                                                            metrics:nil
                                                                              views:NSDictionaryOfVariableBindings(insertedView)]
                                    ]
    ];

}

Basically the one view i want to insert is loaded from a VC

Peter Lapisu
  • 19,915
  • 16
  • 123
  • 179

3 Answers3

8
- (void)addSubview:(NSView *)insertedView fillingAndInsertedIntoView:(NSView *)containerView {

    [containerView addSubview:insertedView];
    [insertedView setTranslatesAutoresizingMaskIntoConstraints:NO];

    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[insertedView]|"
                                                                            options:0
                                                                            metrics:nil
                                                                            views:NSDictionaryOfVariableBindings(insertedView)]];
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[insertedView]|"
                                                                          options:0
                                                                          metrics:nil
                                                                            views:NSDictionaryOfVariableBindings(insertedView)]];

    [containeView layoutIfNeeded];
}
Peter Lapisu
  • 19,915
  • 16
  • 123
  • 179
  • 1
    I think `-layoutIfNeeded` is an `NSWindow` method. Should I call `[containerView.window layoutIfNeeded]` or `[containerView layoutSubtreeIfNeeded]`, or does it matter? – Ben Stock Jul 21 '14 at 15:41
  • in my experience calling layoutIfNeeded was just enought – Peter Lapisu Aug 01 '14 at 17:50
  • you can also refer to http://stackoverflow.com/questions/20609206/setneedslayout-vs-setneedsupdateconstraints-and-layoutifneeded-vs-updateconstra – Peter Lapisu Aug 01 '14 at 17:52
5

constraintsWithVisualFormat returns an NSArray.

@[] is the Objective C literal to create an NSArray.

So, here your method parameter for addConstraints is an NSArray with two elements, each of which is an NSArray.

That's an incorrect method parameter for addConstraints. It expects an NSArray of objects of type NSLayoutConstraint.

Changing your invocation to be along the lines of this will solve the problem:

[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat: etc.

Incidentally, I see so many posts about creating Auto Layout constraints in code. Interface Builder is far the superior method. As Erica Sadun so succinctly puts it in her book iOS Auto Layout Demystified:

Any views you lay out in Interface Builder are guaranteed to be satisfiable. You cannot create a wrong interface with inconsistent rules in IB. The same is not true in code.

Max MacLeod
  • 26,115
  • 13
  • 104
  • 132
  • Ok, but how to set the constraints for the inserted view in IB? As you can manipulate and set constraints only for views presented in xib (the view inserted is in another xib and belongs to different VC) – Peter Lapisu Sep 25 '13 at 13:54
  • yeah fair point. For those I create a container view in the Xib then programmatically add in the subview created from another Xib. Just making it flush to the container. Probably what you're already doing I guess – Max MacLeod Sep 25 '13 at 13:56
2

There are two methods in UIView

//parameter type is NSArray
-(void)addConstraints:(NSArray *) constraints

and

// parameter type is NSLayoutConstraint
-(void)addConstraint:(NSLayoutConstraint *) constraint

So,

constraintsWithVisualFormat 

will return a NSArray, you need use

addConstraints
saneryee
  • 3,239
  • 31
  • 22