ARSCNView Corner Radius not showing - swift

I have a corner radius on my ARSCNView as below;
override func viewDidLayoutSubviews() {
sceneView.layer.cornerRadius = 8
sceneView.layer.masksToBounds = true
sceneView.clipsToBounds = true
}
However, it is only showing when you enter app in background as illustrated below;
As soon as the app is in the foreground the corner radius goes back to 0.
Ive tried adding in ViewDidLoad & ViewWillAppear no success

I just tried with just
sceneView.layer.cornerRadius = 8
without masksToBounds and clipsToBounds and it worked for me.
If you're sceneView is inside another view or the root view of your view controller, check the background of that view and make sure it's something noticeable.
Maybe the sceneView itself is larger than the phones screen. Check the frame size or the layout constraints and make sure they are not causing the sceneView to stretch outside the phone screen edges.
I hope this answers your question.

Related

UINavigationController weird transparency behaviour when presenting

I'm experiencing a weird glitch with the transparent navigation controller. When presenting a view controller with a UIImage at the top of the navigation controller: at first presents half of its background blur with a dark section, and half with a clear one; and after a very short moment it changes for a full dark background. As shown in the gif:
The UIImage displayed is mostly white, the borders are very close to pure white. So the grey color does not make much sense (less sense makes the rapid change).
I did disable extend edges under top bar in the Storyboard for the presented view controller. So the image is not hidden behind the Navigation Controller. With this option enabled the glitch does not appear, but I don't want to hide part of the image.
Disabling the transparency, solves my problem, but I'd like to be able to keep the transparency effect.
Edit: I did notice the "grey effect" also makes the navigation controller opaque. But only for that view, when going back, is transparent again.
Xcode 11, Swift 5, iOS 13.2, iPhone XS.
Thank you very much for your help.
I finally found the problem.
I didn't want the UIScrollView to bounce on top so I used this code:
extension ProblematicViewController: UIScrollViewDelegate {
/// Prevent bounce at top
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y < 0 {
scrollView.contentOffset.y = 0
}
}
}
Which meant the ViewController's Adjust Scroll View Insets were overwrite (I think). So my scroll view did lay under the UINavigationController, to prevent this from happening, I did disable Extend Edges: Under Top Bars, so the root UIView containing the UIScrollView was not covered by the UINavigationController. So the transparency effect could never happen because the view was never under the top bar. More about Adjust Scroll View Insets on this post (helped me to find the problem).
Removing those lines and enabling Adjust Scroll View Insets and Extend Edges: Under Top Bars, solves the glitch problem, but the UIViewController does not have the "prevent bounce on top" behaviour that I wanted.
This kinda explains the weird behaviour of the UINavigationController because the SO has to calculate a transparency over nothing, but is sill strange, the transparency effect is calculated when the ProblematicViewController is fully presented, and not on viewDidLoad() or another view's life cycle before is shown to the user, so the transition is smooth, even when nothing lays behind the effect.

Setting corner radius through viewDidAppear() or viewWillLayoutSubviews()?

In summary, setting the corner radii to get round left and right edges for my UIButtons in my application works by grabbing the buttons bounds and dividing the height by two in viewWillLayoutSubviews(). However, if I navigate to another screen via UIBarButtonItem(), rotate the device, and then navigate back to the screen with the UIButtons() they are NOT round. The corner radii are still based on the button dimensions from the previous orientaion. I tried to use viewDidAppear, but there is a second/noticable delay in setting the corner radii.
Is there anyway to speed the process up of viewDidAppear? I don't think viewWillAppear will work because the view controller isn't aware of the default (square) dimensions of the uibutton(s) I am changing.
The application I am working on is this:
Screenshots of my current application from loading screen to the point of the corner radius not being updated correctly
Use viewDidLayoutSubviews instead, because you'll have the updated bounds at that point, but not yet in viewWillLayoutSubviews.
Or I might suggesting have a button subclass that does the rounding within its own layoutSubviews, freeing your view controller from having to iterate through buttons and rounding them.
For example:
#IBDesignable
class RoundedButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
let radius = min(bounds.width, bounds.height) / 2
layer.cornerRadius = radius
}
}
And then just use this class instead of UIButton. That yields:

How to prevent SpriteKit overlay in SceneKit to stretch?

In WWDC 2017 SceneKit session they recommend using overlaySKScene to overlay a SpriteKit layer over SceneKit for HUD, etc. It seems to work fine until I rotate the iPhone/iPad. Now the text in SpriteKit all got stretched (if turn from portrait to landscape) or shrunk (if turn from landscape to portrait). Is there anyway to keep the text or graphics in same size regardless of orientation?
sceneView.overlaySKScene = SKScene(size: sceneView.frame.size)
I solved the issue in a very simple way. Just resize the overlaySKScene and reposition everything in
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
let width = sceneView.frame.height
let height = sceneView.frame.width
sceneView.overlaySKScene?.size = CGSize(width:width, height:height)
...
}
Hope this helps others facing similar problem.
You need to look at how SKScene works:
This means set the overlay to size of the iphone screen for the given orientation:
sceneView.overlaySKScene = SKScene(size: sceneView.frame.size)
Now I am assuming nothing else changes, so that means your scaleMode is set to .fill, which means stretch graphics till all sides are filled in.
When sitting in portrait mode, you will not notice anything because it is 1:1 scale.
Now you flip it to landscape.
The system is going to attempt to convert your portrait screen size to a landscape size.
This means you are going to get fat stubby graphics because it is going to stretch out your sides, and shrink your top and bottom to fill all edges.
This is why doing code like sceneView.overlaySKScene = SKScene(size: sceneView.frame.size) is bad. You end up getting yourself confused.
I always recommend either using an SKS file, or setting a constant scene size, so sceneView.overlaySKScene = SKScene(size: CGSize(750,1334))
Then, depending on how I want to display my overlay, I use the proper scale mode.
In games where I want the overlay to take up the exact percentage of screen space, I use .aspectFill
In games where I want the overlay to take up the exact amount of pixel space, I use .resizeFill
By looking at the scaleMode, I now know how my scene is suppose to behave.
With .aspectFill, I am going to need to detect when orientation was flipped, and at that time either present the SKS corresponding to orientation, or move nodes corresponding to orientation.
With .resizeFill, I need to create a resize method that adheres to when the orientation is flipped, and move the nodes in proportion to the new size.
You can detect when orientation flips in the ViewController with
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
then use the view to get to the scene to call your resize function/load a new scene.

SKSpriteNode with a size relative to the screen

I'm trying to create a 'modal' SKSpriteNode that fills most of the screen minus a border on each side. I have a subclass of SKSpriteNode as I need to pass some other info to it for display purposes, so I have a custom init method.
After I initialise my Modal I'm then setting the size as below:
let modal = Modal(items: [Item])
let newSize = CGSize(width: (frame.width) - 40, height: (frame.height) - 40)
modal.size = newSize
modal.zPosition = 999
addChild(modal)
The trouble is there is no border at the top or bottom on my Modal, it fills the entire screen vertically. My custom 'init' method of modal calls the super.init passing in a size of 50,50 so even that should be a lot smaller then the screen if that's what it was using but it's not. My game is in landscape mode and I tried switching the width and height above but that fills the entire screen (so there's no border on the left and right either). I know I've not set the position in the above code, but even then I would expect to see a 'border' somewhere evening if it isn't uniform.
This is all done in my main scene file, so frame here relates to the frame of the main game scene.
Any ideas?
So for anyone else has a similar issue the problem was that my scene was loaded from an SKS file.
The SKS file in question had it's size set to freeform. Changing this to a specific device e.g iPhone 6 and making sure the orientation was set to landscape has fixed the issues with sizing

Subview not resizing proportionate to super view

I have a gameView(Just a blue color view with grid lines). I have pinned this gameView to the bottom and the sides of the screen and set the height to 475. When a user taps on this view, I locate the point and create a custom view(fenceView) with the origin and frame of the cell(width and height). In the init method of the fenceView I create a new UIImageView of a fence image and add it as a subview.
Because of autolayout, when the device is rotated, the width of the gameView changes accordingly. But the problem is, the added fenceViews do not resize. I tried to set the autoresizingMask = [.FlexibleWidth, .FlexibleHeight] for both the gameView and the fenceView. But it did not solve the issue.
We can see that in the landscape mode, the fence images are not displayed properly. It might be small mistake that I am doing, but I am not able to solve this issue since two days. Any help is greatly appreciated.
.FlexibleHeight does not need to be used since the overall height will always be 475. Try setting the autoresizingMask = [.FlexibleWidth, .FlexibleLeftMargin, .FlexibleRightMargin].
The width will need to change as well as its X position for the larger/smaller width. Both flexible Left and Right margin will apply the increased width to both sides.