Enable and disable auto rotate programmatically using Swift? - ios

I would like to programmatically disable or enable the auto rotate function using a button using Swift. I was thinking that it might be able to somehow be done using the supportedInterfaceOrientations() function, but I am very confused after looking through the literature about how this is done. Is there an easy solution for this?

You could create an action for the button that sets a boolean flag somewhere in your code and return the value of that flag in the shouldAutorotate method of the view controller. If you need that for all view controllers you could create a common base view controller (inheritance).
Example of button action:
#IBAction func toggleRotation(sender: Button) {
// A made up AppConfig class with class method for setting and retrieving
// rotation flag.
AppConfig.allowRotation(!AppConfig.allowRotation)
}
Example of shouldAutorotate:
override func shouldAutorotate() -> Bool {
return AppConfig.allowRotation()
}
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/#//apple_ref/occ/instm/UIViewController/shouldAutorotate

Related

Hide home button on iPhone X

I have to figure out a way to hide the home button for all of my View controllers in the app.
Yes
override var prefersHomeIndicatorAutoHidden: Bool {
return true
}
is an option but what if I have like 100 VCs, is this the only way?
I use navigation controller so I tried to override this property there, but it doesn't seems to have a reflection on the others as well.
Any ideas? Thanks in advance.

UIStoryboardSegue animates property in subclass

I have a UIStoryboardSegue subclass for replacing current view controller with next view controller.
As we have a Animates property in interface editor, I want to access this property in the subclass.
My code is following:
class ReplaceSegue: UIStoryboardSegue {
override func perform() {
var viewControllers = source.navigationController?.viewControllers.dropLast() ?? []
viewControllers.append(destination)
source.navigationController?.setViewControllers(viewControllers.map {$0}, animated: true) // I dont want this `true` to be hardcoded
}
}
As per comments in UIStoryBoardSegue class
The segue runtime will call +[UIView setAnimationsAreEnabled:] prior
to invoking this method, based on the value of the Animates checkbox
in the Properties Inspector for the segue.
So obviously you can read the value of animate check box by using
UIView.areAnimationsEnabled
So in my custom segue
class MySegue: UIStoryboardSegue {
override func perform() {
debugPrint(UIView.areAnimationsEnabled)
}
}
This prints false if animate checkbox is unchecked or true if it is checked :)
So in your case
class ReplaceSegue: UIStoryboardSegue {
override func perform() {
var viewControllers = source.navigationController?.viewControllers.dropLast() ?? []
viewControllers.append(destination)
source.navigationController?.setViewControllers(viewControllers.map {$0}, animated: UIView.areAnimationsEnabled)
}
}
I hope whats happening is already clear, incase you still have doubt, here is the explanation, iOS checks the animates checkbox value and uses it to set whether animations are enabled or not by calling setAnimationsAreEnabled with the value of animates check box in interface prior to calling perform() method.
So when the control reaches inside perform you can be assured that iOS has already read the value of animates check box and used it to set setAnimationsAreEnabled all you have to do now is to ask areAnimationsEnabled to get the value of animates check box.
So that should provide you the value of animates checkbox :)
Hope it helps :)
You shouldn't need a UIStoryboardSegue subclass for this. The docs state "You can subclass UIStoryboardSegue in situations where you want to provide a custom transition between view controllers". This means that a replacement without without any animation isn't a custom transition, thus shouldn't use a segue subclass.
The correct way to do replacement is to use a Show Detail (e.g. Replace) segue and inside the parent view controller that is managing the child view controllers implement the method showDetailViewController and replace the children, e.g.
#implementation DetailNavigationController
- (void)showDetailViewController:(UIViewController *)vc sender:(id)sender{
[self setViewControllers:#[vc] animated:NO];
}
If you didn't know, the Show Detail segue (after magically instantiating the destination view controller) has a perform method that just calls showDetailViewController on self, and the base UIViewController implementation searches up the view controller hierarchy looking for one that overrides showDetailViewController, so you can intercept it and perform your custom code, before say it goes up to another parent that might implement it also like a split view.

How to move focus at button in collectionview cell in tvos application?

I am working on apple TV application. In my app, I have made a screen which has a collection view. In that case, I am able to move focus at collection view cell but not able to move focus to the button which is in collection view cell so can anyone help me to solve this issue ?
please give me an answer if anyone knows this answer.
I am able to solve this problem by adding below methods in collectionViewCell subclass.
In CollectionViewCell Subclass
override var preferredFocusEnvironments: [UIFocusEnvironment]{
// Condition
}
override func shouldUpdateFocus(in context: UIFocusUpdateContext) -> Bool {
// Condition
}
override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
// Condition
}
you can see more at this link:
enter link description here.
I think this page will guide to achieve what you want. https://developer.apple.com/library/content/documentation/General/Conceptual/AppleTV_PG/WorkingwiththeAppleTVRemote.html#//apple_ref/doc/uid/TP40015241-CH5-SW4
It give good explaination of how focus engine will decide which object should get next focus. Below is great explanation step by step at above link.
Here is an example showing how focus might be determined:
The focus engine asks the root window for its preferredFocusedView,
which returns its root view controller’s preferredFocusedView
object.
The root view controller, a tab view controller, returns its
select view controller’s preferredFocusedView object.
The select view controller overrides its preferredFocusedView method to return a specific UIButton instance.
The UIButton instance returns self(the default), and is focusable, so it is chosen by the focus engine as the next focused view.
You have to override the preferredFoucsedView property of your UIView or UIViewController.
override weak var preferredFocusedView: UIView? {
if someCondition {
return theViewYouWant
} else {
return defaultView
}
}
Thanks to Slayter's answer

Restricting portrait orientation to collectionview in iOS doesn't seem to work

I have multiple viewControllers in my app and I would like to restrict certain views only to portrait orientation. I have achieved this by overriding shouldAutoRotate and supportedInterfaceOrientations like below
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientation.Portrait.rawValue)
}
I have followed the same for a UICollectionView but it doesn't seem to work. I would like to know if this is the right way to achieve it. Help on this would be much appreciated. Thanks in advance!
In iOS 8 or later, if you want to control the allowed orientations per view controller:
Make sure the "Supported interface orientations" in the Info.plist allows all orientations you want the app to be able to use. (Or just check the correct "Device Orientations" in the Xcode UI interface to the Info.plistfile)
Per view controller, implement (example restricting to portrait):
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
A problem you can run in to is if your view controller is embedded in another view controller (like an UINavigationController or a UITabBarController, or both).
I suspect this is the situation you are describing.
If so, all view controllers involved need to implement the supportedInterfaceOrientations() method. AFAIK, if you for example have a UINavigationController above your view controller, you need to sub class and create your own navigation controller with the method implemented.

Swift Orientation override for a viewcontroller

I'm having trouble to allow only 1 view controller in marking portrait,Landscape right and left, that view controller has a button to a video on youtube embed link I just want to allow rotation to this view,
I allowed all orientations in app and tried to add this to other view controllers that I wanted to be portrait but no chance
override func supportedInterfaceOrientations() -> Int {
return UIInterfaceOrientationMask.Portrait.rawValue.hashValue | UIInterfaceOrientationMask.PortraitUpsideDown.rawValue.hashValue
}
is there anyother way to implement this I mean I will only allow portrait in general app setting but override one that in the video view controller view,or just like first one I tried in general setting allow all orientations but allow only portrait in all views except videocontrollerview, thanks advance for any help..
Since there is no code I can't say for sure but you might be missing this in your view controller so that those supportedInterfaceOrientations can work:
override func shouldAutorotate() -> Bool {
return true
}

Resources