This is my custom UIView:
After I rotate to horizontal, and then back to Portrait it looks like this:
Why?
After I rotate device this method is called:
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
tableView.reloadData()
}
What Am I doing wrong? It works perfect for ios8, but not for ios9
Related
To make it more clear I have created a demo app with only 2 ViewControllers. The issue only occurs on iPad on which I have kept all orientations enabled which are already enabled by default. So if I present a UIViewController as FormSheet on iPad, the viewWillTransition method is not triggering sometimes when iPad is in landscape mode. I tested it both in simulator as well as on the physical device. Firstly I thought it might be due to my code but in this demo it was clear, if I try to print a statement in viewWillTransition method in my ViewController, it will be printed every time no matter which orientation you are in. However, when I present a FormSheet, it will work for every orientation if iPad is in Portrait mode but if you switch to landscape mode, and try to change app size in Split View, sometimes the statement is not printed. It also happens if you have 2 apps opened in Split Mode with equal ratio and you switch your app to slideOver. So im confused why viewWillTranstion working fine for portrait mode but sometimes will not trigger for landscape mode?
This is my code in ViewController:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
}
#IBAction func button(_ sender: Any) {
let vc = storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
if self.traitCollection.userInterfaceIdiom == .phone {
vc.modalPresentationStyle = .fullScreen
}
else {
vc.modalPresentationStyle = .formSheet
}
vc.modalTransitionStyle = .coverVertical
self.present(vc, animated: true, completion: nil)
}
}
And this is code for SecondViewController:
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
DispatchQueue.main.async {
print("Transition Detected")
}
}
}
Here is a video in which you can see the statement is only getting printed in portrait mode: https://youtu.be/iz5iOzOtGCg
It gets printed in landscape mode too but I have included the part ion which viewWillTransition is not triggering.
In Portrait mode, no matter what you do, rotate, change to Split View or drag size of app in Split View, or switch app to slipover, Transition Detected is printed. However in landscape mode, it will not print if you are in Split View and drag to make app small.
This behaviour is so confusing. Any idea how to detect all the transitions in landscape mode too?
My application has a UIViewController where uses the new .pageSheet modal presentation style introduced on iOS 13.
This UIViewController has a UINavigationBar on the top and it's pinned, by constraints, at the top, leading and trailing.
I noticed that the background from this view bleeds in white while the UIViewController is animating. Take a look on this recorded GIF from a real device:
Is there anything I can do to solve this? The UIViewController and UINavigationBar were created programatically.
Maybe doing this can solve it?
override func layoutSubviews() {
super.layoutSubviews()
var originalFrame = frame
frame = originalFrame
}
I am using Swift 5.1 and Xcode 11.3. The iPhone is running iOS 13.1.3.
Probably you set the view's layer to rasterize, this is making with the .pageSheet animation not draw it correctly.
The solution, remove the code below:
navigationBar.layer.shouldRasterize = true
navigationBar.layer.rasterizationScale = UIScreen.main.scale
I have an activity indicator that gets presented on an iPhone and iPad. In the iPad in split screen mode it gets presented to whichever side of the view that called it. I would instead like it to get presented in the middle/center the window's screen. If I do it this way wether on the iPhone in portrait or iPad in split screen mode it will always be in the center of the screen.
How do I do this?
MyView: UIViewController{
let actInd = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
#IBAction fileprivate func buttonPressed(_ sender: UIButton) {
guard let window = UIApplication.shared.keyWindow else { return }
//how to add actInd as subview to the window' screen?
actInd.startAnimating()
}
}
It's pretty simple. Turn off the auto-resizing mask. Add the add actInd to window, then set the center anchors.
actInd.translatesAutoresizingMaskIntoConstraints = false
window.addSubview(actInd)
actInd.centerXAnchor.constraint(equalTo: window.centerXAnchor).isActive = true
actInd.centerYAnchor.constraint(equalTo: window.centerYAnchor).isActive = true
Window is subclass of UIView. Just add it as it's subview like you're adding a view to another view. But remember that window is shared throughout your app, so adding it every-time will consume memory, remove it after your job is done.
If you want to center it in the window, you can use autoResizingMask or add constraints to it.
Using Xcode 7 I wanna to create a small application with a UIWebView.
This app will have to run it from all devices.
I'm using "New iOS Launch Image" in Assets.
But when the "Launch" terminate there is a waiting time (which varies from connection speed ) before that WebView is loaded .
In this time I would like to "Launch Screen" that continue to persist using the Image for the type of device .
Can you help me?
You cannot increase the time of splash screen as recommended by apple but you can do something which will make the user feel like splash screen is still there.
You can achieve it in this way:
I am assuming that the first screen load after your splash screen is your WebView screen. Add UIImageView on your WebView in interface builder and set splash screen image on your ImageView. Now make IBOutlet for this imageView and set it hidden property as yes when webview intimates you that its loaded in its delegate methods. Don't forget to set the delegate of your UIWebView in interface Builder.
class WebViewController: UIViewController, UIWebViewDelegate {
#IBOutlet var UIImageView: imgThumbSplash!
override func viewDidLoad() {
super.viewDidLoad()
imgThumbSplash.hidden = false
}
func webViewDidFinishLoad(webView: UIWebView){
imgThumbSplash.hidden = true
}
func webView(webView: UIWebView, didFailLoadWithError error: NSError?){
imgThumbSplash.hidden = true
}
}
I solved it with this code:
extension UIImage {
convenience init?(fullscreenNamed name: String) {
switch UIScreen.mainScreen().bounds.size.height {
case 480: //iPhone 4/4s
self.init(named: "\(name)-700#2x.png")
case 568: //iPhone 5/5s
self.init(named: "\(name)-700-568h#2x.png")
case 667: //iPhone 6/6s
self.init(named: "\(name)-800-667h#2x.png")
case 736: //iPhone 6+/6s+
self.init(named: "\(name)-800-Portrait-736h#3x.png")
default:
self.init(named: name)
}
}
}
I take in "LaunchImage" the right image for the device screen in use.
I am making a SpriteKit game that runs in both landscape modes. How can I pick the default landscape orientation?
When I first load the game it loads in landscapeLeft (home button is on left)
Looking at most games on the app store it seems the default orientation is the other way around (landscape right). I also prefer it to be that way.
I have tried playing around with the info.plist but couldnt find anything.
I dont see what i can change in my viewController either because I want to keep both landscape orientations.
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return .Landscape
} else {
return .Landscape
}
}
Anyone know what I have to do?
Thanks in advance
Just change the order of items for Supported Interface Orientation key inside info.plist. The app will launch in whatever orientation is specified in the first item. By default, that would be landscape left. Just drag Item 1 (landscape right) in the place of Item 0 (landscape left):
You can set this in the View Controller by overriding:
override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
return UIInterfaceOrientation.LandscapeLeft
}
Just return the orientation you want for the game View Controller.