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.
Using Stack View.
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.
Related Topics
Application Identifier Entitlement Value Has Changed
Sending Latitude and Longitude to Server When App Is in Background
Removing Wkwebview Accesory Bar in Swift
Enable Uialertaction of Uialertcontroller Only After Input Is Validated
Cncopycurrentnetworkinfo with iOS 13
Make Swift Assume Degrees for Trigonometry Calculations
Uitableviewcell Textlabel Color Not Changing
Xcode 6.3: Could Not Load Nib in Bundle
How to Find Serial Number, Imei Number Using iOS Sdk
Detect Hotspot Enabling in iOS with Private API'S
How to Convert Xcode 32 Bit App into 64 Bit Xcode App
Share Datas Between Two Apps with iOS 8 App Groups (Using Nsuserdefaults)
Nsinteralinconsistencyexception - Uikeyboardlayoutalignmentview
How to Create the Current Date (Or Any Date) as an Nsdate Without Hours, Minutes and Seconds
Can the -Objc Flag Be Applied Selectively to Static Libraries