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

跟風遠走 提交于 2019-11-27 20:27:44

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.

I faced a similar situation.

I created two sets of NSLayoutConstraints in interface builder. Each set for one case. One set was "installed" the other not.

When I switch the case the coresponding set of layout constraint was activated and the other was deacticated. An as described in the Qusteion rotating forth and back does not work properly.

Is solved this by installing both sets in interface builder. And to get rid of the warnings I used a slighlt lower priority (999) for the second set. This worked for me.

Btw: Strang i used the "installed/not installed" aproach on another viewcontroller, their it worked.

In the not working case the viewcontroller was embedded in a containerview, perhaps that was the reason.

You can use this workflow, even though it’s clear that this is not a supported use case currently for the folks at Apple.

The trick is to not uninstall constraints (as @matt also pointed out), but to deactivate them in the viewDidLoad() of your UIViewController subclass, before layout occurs (and your conflicting constraints cause a problem).

I’m using that method now and it works perfectly. Ideally, of course, we’d have the ability to visually create groups of constraints and use them like keyframe simply by activating and deactivating them (with free animations in between) :)

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