Constraints are not working when changing view orientation - ios

How to force update constraints to position view correctly
My app supports only Portrait orientation, but one view controller should always open in landscape mode. I managed to change orientation forcefully and working properly.
But my view constraints are not working properly when navigating to that view for the very first time or navigate after changing orientation of device. Once it loaded and no orientation change happen its view loaded as expected. Constraints are not framing sub view properly in orientation changed when device is already in that orientation. I am working in xcode 8.2.1.
I checked many links but didn't find any solution for this problem. I tried to update view and constraints also.
self.view.setNeedsUpdateConstraints()
self.view.setNeedsLayout()
self.view.setNeedsDisplay()
self.view.setNeedsFocusUpdate()
Code I am using is -
override func viewDidLoad()
{
super.viewDidLoad()
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
}
override func viewWillDisappear(_ animated: Bool)
{
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
}
override var shouldAutorotate: Bool
{
return true
}
View loaded as this when my device is in already in landscape mode and i navigate to this view controller and force for landscape mode. It updated to landscape mode but don't update constraints.
When press back and again select the option it shows as it should be in landscape mode.

Related

How to allow only single UIViewController to rotate upside down with Xcode?

In my app all screens have portrait orientation. How to allow only single UIViewController be in two orientation mode: portrait and upside down? When user rotates an iPhone, the UIViewController should rotates too.
First of all, In your application all screens except one screen are in portrait orientation. So You cannot set orientation of your application as portrait. So Set Device Orientation as portrait and LandScape both.
Put following code on which screen you need landscape orientation in ViewDidLoad
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
and
override var shouldAutorotate: Bool {
return true
}
Put following code on all screens where you need only portrait orientation in viewDidLoad
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
If you have any function that continuously called then you can check the device orientation inside this function as-
if UIDevice.current.orientation == UIDeviceOrientation.portraitUpsideDown {
// set your view constraints
}
if UIDevice.current.orientation == UIDeviceOrientation.portrait {
// set your view constraints
}
Otherwise you should create a monitoring function and check device orientation inside the function.

How can I enable rotation of screen programmatically in Swift?

I am have 3 VC and in Xcode I enabled only Portrait mode but for one VC need enable Landscape Left & Right mode.
How I can enabled these orientation programmatically?
I am try use this code but it's don't help me:
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .all
}
override open var shouldAutorotate: Bool {
return true
}
Also did try use next way:
Enable all screen orientation on xcode, and set for two VC only portrait mode, it's not bad BUT my VC have few subviews and when I hold phone in landscape orientation and then start program, VC have portrait orientation but other subview which I am create PROGRAMMATICALLY change self position on screen.
How I am can solve this problem?

Need some controllers in landscape

I have complex application with lot of ViewControllers. The whole app is designed to be in portrait mode and its locked to it.
Now I need part of app to be able to show content in landscape. Everything is working fine, excluding one scenario:
I'm on controller, which is locked to portrait and has device in landscape position - I navigate to new controller, which is landscape enabled. Then the new controller doesn't rotate to landscape. If I rotate phone to portrait and landscape again, the controller rotates correctly (if I enter the new controller with device in portrait, everything is fine and window rotates, if I rotate device.
I tried:
let value = UIDevice.currentDevice().orientation.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")
in viewWillAppear, but it didn't work (I suppose it can't work, because UIDevice.currentDevice().orientation is in requested orientation already.
Try adding this to your code and see if you get the results you are expecting.
override func viewDidLoad() {
let value = UIInterfaceOrientation.Portrait.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")
shouldAutorotate()
}
override func shouldAutorotate() -> Bool {
switch UIDevice.currentDevice().orientation {
case .Portrait, .PortraitUpsideDown, .Unknown:
return true
default:
return false
}
}

Swift: how to correctly rotate UITableViewController and UIViewController and in portrait mode

In my iOS app I want some controllers to have only .Portrait mode and moreore I would like them to rotate in .Portrait mode when coming from a controller allowed to be in .Landscape mode. I thought that implementing the following method in these .Portrait only view controllers was the right way:
override func viewWillAppear(animated: Bool) {
self.automaticallyAdjustsScrollViewInsets = true
super.viewWillAppear(animated)
let value = UIInterfaceOrientation.Portrait.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")
}
Anyway the result I get is not correct. For example the following is a .Portrait only UITableViewController and when viewWillAppear() is called, instead of this
I instead get the following
This happens also with UIViewController. It's like the view (or the table view) is not rotated and remains in .Landscape mode. What am I missing?
Do you play with Auto-Layout? When I set leading edge, trailing edge everything goes right.
Another solution can be recalculate manually the textView:
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
textView.frame = CGRect(x: textView.frame.minY, y: textView.frame.minX, width: textView.frame.height, height: textView.frame.width)
}
UPDATE
I tested my previous solution and it doesn't work, but I found another way. Actually you need to rotate it and call viewWillAppear one more time - it works for me, try this:
if orientation.isLandscape{
let value = UIInterfaceOrientation.Portrait.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")
viewWillAppear(false)
}
No - it doesn't work for all cases...
I'm testing it like this:
I'm in app,
Mobile rotation to landscape, in tab bar item (where is not checked orientation). After that I tap on tab bar item where I checked orientation, and I rotate)
It rotates nicely without your problem, and when I'm doing it one more time the problem shows. But when I tap on another tab bar item and come back, everything goes right - I think we should call some method, I still don't know which one.

Force Landscape orientation, Swift

I have a view controller that is designed in portrait view. I have another view controller designed in Landscape view (in storyboards). On my first view controller (portrait VC) i have a button that takes you to the landscape VC. When you click on the button the Landscape view controller shows up in portrait view initially and doesn't change until rotated. I would like to have this landscape view controller automatically show up in landscape without having to rotate it.
Ive been coding this in swift, and have had no luck. In my plist menus i have all orientations enabled.
Any help would be great.
You should add this in the second viewcontroller (designed to be in landscape) in the viewDidLoad
It is in swift3 :
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation()
Hope it will help you :)
I believe the best and most robust way to achieve this is by overriding two attributes - and avoid force orientation changes of the windows (as suggested by others).
This is how I got one of my view controllers to always show up in landscape mode, and stay there, without affecting the entire navigation stack. Add both of these overrides to the landscape view controller:
override var shouldAutorotate: Bool {
false
}
This will prevent the view controller from auto-rotating when device orientation changes. Now that the view controller no longer rotates by itself, all you need to do is request the orientation you want:
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
UIInterfaceOrientation.landscapeLeft
}
And voila! Should do what you want.
I'm working on a similar scenario I want to load and keep my first ViewController in Landscape orientation while allowing subviews to switch as needed
I think placing
override func viewDidLoad() {
super.viewDidLoad()
let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")
}
Swift 4
override func viewDidLoad() {
super.viewDidLoad()
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
}
should load your view in landscape mode...But if holding phone in portrait orientation it will soon rotate...and that's the part I'm at...How to prevent the rotation.

Resources