Activateconstraints: and Deactivateconstraints: Not Persisting After Rotation for Constraints Created in Ib

activateConstraints: and deactivateConstraints: not persisting after rotation for constraints created in IB

The problem is that you are doing something incoherent with "uninstalled" constraints in the storyboard. They are there but not there. "Uninstalled" constraints are for use only with size classes! You use them if you are going to let Xcode swap constraints for you automatically on rotation. Xcode can't cope with what you're doing. But if you create the second set of constraints in code, everything will work fine.

So, do this. Delete the two "uninstalled" constraints, and delete the uninstalledConstraints outlet. Now replace your entire view controller code with this:

@property (strong, nonatomic) NSMutableArray *c1;
@property (strong, nonatomic) NSMutableArray *c2;
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *installedConstraints;
@property (weak,nonatomic) IBOutlet UIButton *button;
@end

@implementation ViewController {
BOOL did;
}

- (void)viewDidLayoutSubviews {
NSLog(@"did");
if (!did) {
did = YES;
self.c1 = [self.installedConstraints mutableCopy];
self.c2 = [NSMutableArray new];
[self.c2 addObject:
[NSLayoutConstraint constraintWithItem:self.button attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTopMargin multiplier:1 constant:30]];
[self.c2 addObject:
[NSLayoutConstraint constraintWithItem:self.button attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeadingMargin multiplier:1 constant:30]];
}
}

- (IBAction)switchconstraints:(UIButton *)sender {
[NSLayoutConstraint deactivateConstraints:self.c1];
[NSLayoutConstraint activateConstraints:self.c2];
NSMutableArray* temp = self.c1;
self.c1 = self.c2;
self.c2 = temp;
}

Now repeatedly press the button. As you see, it jumps between the two positions. Now rotate the app; the button stays where it is.

Keep autolayout constraints active status on device rotation

Size Classes

Installed refers to Size Classes installation, not to active/inactive.

You must create another constraint programmatically, and activate/deactivate that one. This is because you cannot change the multiplier of a constraint (Can i change multiplier property for NSLayoutConstraint?), nor can you tinker with Size Classes (activateConstraints: and deactivateConstraints: not persisting after rotation for constraints created in IB).

There are a few ways to do so. In the example below, I create a copy of your x1 constraint, with a multiplier or 1/2. I then toggle between the two:

@IBOutlet var fullWidthConstraint: NSLayoutConstraint!
var halfWidthConstraint: NSLayoutConstraint!

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
halfWidthConstraint = NSLayoutConstraint(item: fullWidthConstraint.firstItem,
attribute: fullWidthConstraint.firstAttribute,
relatedBy: fullWidthConstraint.relation,
toItem: fullWidthConstraint.secondItem,
attribute: fullWidthConstraint.secondAttribute,
multiplier: 0.5,
constant: fullWidthConstraint.constant)
halfWidthConstraint.priority = fullWidthConstraint.priority
}

@IBAction func changeConstraintAction(sender: UISwitch) {
if sender.on {
NSLayoutConstraint.deactivateConstraints([fullWidthConstraint])
NSLayoutConstraint.activateConstraints([halfWidthConstraint])
} else {
NSLayoutConstraint.deactivateConstraints([halfWidthConstraint])
NSLayoutConstraint.activateConstraints([fullWidthConstraint])
}
}

Tested on iOS 9+, Xcode 7+.

How can I change layout constraints depending on portrait/landscape programatically?

Well you can do something like this:

Declare variable to hold constraints.

var cryptoIconImageCenterXWhenPortrait : NSLayoutConstraint?
var cryptoIconImageCenterXWhenLandscape : NSLayoutConstraint?

Define both contraints

cryptoIconImageCenterXWhenPortrait = cryptoIconImage.centerX.constraint(equalTo: window.centerX)
cryptoIconImageCenterXWhenLandscape = cryptoIconImage.centerX.constraint(equalTo: window.centerX, constant: -20)

Activate them accordingly

If Landscape {
cryptoIconImageCenterXWhenPortrait.isActive = false
cryptoIconImageCenterXWhenLandscape.isActive = true
} else If Portrait {
cryptoIconImageCenterXWhenPortrait.isActive = true
cryptoIconImageCenterXWhenLandscape.isActive = false
}

How to make constraints work for landscape and portrait (xcode 8.1 / swift3 / storyboard)

I have done it in two way.

  1. Using Stack View.

  2. Scroll View as your requirement.

    I have added the image and all the design are done in storyboard so I am giving you git link. Demo Project Link
    Hope it will help for you.
    Sample Image
    Sample Image



Related Topics



Leave a reply



Submit