Behold! After 2 days of searching I believe I may have an answer. Admittedly it cannot be done without code however.
First create your usual top, bottom, leading and trailing constraints from the contentView to the Scroll view.
However with the leading and trailing, tick the "Placeholder - Remove at build time" option.
Then inside your viewDidLoad method add the following:
NSLayoutConstraint *leftConstraint =[NSLayoutConstraint
constraintWithItem:self.contentView
attribute:NSLayoutAttributeLeading
relatedBy:0
toItem:self.view
attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:0];
[self.view addConstraint:leftConstraint];
NSLayoutConstraint *rightConstraint =[NSLayoutConstraint
constraintWithItem:self.contentView
attribute:NSLayoutAttributeTrailing
relatedBy:0
toItem:self.view
attribute:NSLayoutAttributeRight
multiplier:1.0
constant:0];
[self.view addConstraint:rightConstraint];
This dynamically adds the leading and trailing constraints from your contentView to the controller's main view (i.e. outside the scroll view).
Then when you rotate your device the input fields are stretched appropriately.
This solves your rotation problem, regarding the keyboard appearing there's other answers to this on SO, but basically inside viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardDidHideNotification object:nil];
then add these 2 methods:
- (void) keyboardWasShown:(NSNotification *)notification
{
NSDictionary *info = [notification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
}
- (void) keyboardWillBeHidden:(NSNotification *)notification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
}