In storyboard, I have buttons attached to main view as siblings to SCNView(both buttons and SCNView are subviews of main view). At launch time, the buttons appear on screen before the SCNView does. This is quite unfortunate. Do you have any idea how to fix this?
//edit: added button programatically in viedDidLoad: as a subview of SCNView..Still the same problem.
SettingsButton and View appear before SceneView. This happens on iPhone 5,5c and lower and on iPads.(3 for sure, don't know for others)
Code for adding view programatically:
let uv = UIView(frame:myFrame)
uv.backgroundColor = UIColor.blackColor
sceneView.addSubview(uv)// scene view from storyboard
Thats it. How can iOS take 5-10s to load an app, but than rushes with adding views to the screen in an unpredictable order.. Couldn't it just take 0.2s more and present view properly? Really stupid problem
I imagine if you check via debugger breakpoints or logging in viewDidLoad, you'll find that the SCNView instance is indeed in the view hierarchy immediately.
What you're seeing is that said view's SceneKit content does not appear immediately. Depending on what you're doing with SceneKit, it may take some time to load content and prepare for rendering, and during that time the rest of the view hierarchy remains visible. That delay is probably unavoidable — you might be able to minimize it by optimizing asset formats, reducing the amount of stuff in your scene, etc. So it sounds like the key issue here is getting your app launch experience to look the way you want while accounting for the delay.
A good way to do that might be to show a splash image of some sort until SceneKit is ready to display. You could put a UIImageView in your storyboard, set up to obscure everything with a splash screen (possibly the same launch image iOS displays before your app takes over), then hide that image view (with a fade out even?) when SceneKit starts rendering.
To find out when SceneKit starts rendering, make one of your objects the scene renderer delegate and implement renderer:didRenderScene:atTime:. That method gets called on every frame, so you can use it to catch when the first frame has been rendered (and then ignore it for subsequent frames).
Related
EDIT: https://bitbucket.org/KevinvandenhoekBeast/avplayerlayerpopgesture/overview <-- A simple sample project that recreates the problem, click on the video to push the detailviewcontroller, then popgesture back. The animations happen in the NavigationAnimator, and the popgesture logic is in the NavigationInteractor. The NavigationTransitioningView protocol defines the methods that are used by the animator to transition the video from one frame to the other.
Hello fellow developers,
For the past few evenings I’ve been struggling with a persistent and 100% reproducable animation glitch. I’ve been working on an app that has custom navigation transition animations that work both ways (push and pop). The transition I made is having a UIView type object moving in the transitioncontext from 1 view to the other, and so far it’s been working wonderfully using a protocol that I made for the two involved viewcontrollers, which lets them tell the animator what view they want to transition, and their respective from and to frames.
I use this on images, and on videoplayers, IE when the user clicks on an image in a collectionView the image frame animates from its origin in the original viewcontroller towards the position it should take in the detailViewController. The same happens for playing videoplayers. It works perfectly when I simply push a viewcontroller, and pop, for both videoplayers and images. However, recently I implemented a custom pop gesture (with a UIPercentDrivenInteractiveTransition subclassing class). The popgesture seemed to work wonderfully and I was looking at some beautifully lerped animation states, until I tried it with a videoplayer and the horror started.
When doing the popgesture with a videoplayer that is animated from one frame to another (as in CGRect) there is some extremely glitchy behaviour. The popgesture pretty much consistently cancels after a (very) short amount of time, generally at about 0.1 ish progress (an interesting detail: if I swipe very quick the gesture is completed and nothing bugs/glitches), but despite cancelling, the pop does (seem to) happen and I land back at the previous viewcontroller. This is where things get really funky. The visibility / frame of the viewcontroller is changed somewhat, like there is some clipping (somewhere past halfway the view cuts off), and the entire view seems to be shifted (upwards in my case), and generally repeating the popgesture worsens things. However, tapping on the view still responds as if the view is in its normal position (without the shift upwards). This leads me to believe this is some sort of a layer glitch with some of the stuff happening when animating an AVPlayerLayer with a UIPercentDrivenInteractiveTransition.
When I don't update the playerlayer containing view it’s frame while animating, the bug doesn’t occur. Similarly, when I remove the player’s layerClass override, and simply add an AVPlayerLayer as a sublayer (and update it’s frame in the layoutSubviews call), I also don’t experience the bug, but I get the side effect that the playerlayer immediately jumps to it’s final frame, despite the containing view animating properly).
I’m sincerely hoping there is someone that has a deeper knowledge in CALayers, and maybe recognizes these symptoms and could hopefully point me to what’s really causing them. Many thanks in advance.
I useful, I’m willing to upload a video of the issue.
tl;dr using a custom UIPercentDrivenInteractiveTransition subclass to lerp the frame property of a view with a layerClass of AVPlayerLayer from 1 CGRect to another causes very strange things to happen in the destination viewcontroller (its root view visually shifting / changing frame / clipping, while the touch area is as if the view isnt shifted (IE tapping a collectionViewCell highlights / selects the cell above)), despite the exact same animation logic working flawlessly when used without the UIPercentDrivenInteractiveTransition subclass popgesture handling.
I am creating a camera roll feature similar to snapchat where the camera is the bottom layer and then after tapping a button the camera roll appears. The camera roll does not occupy the whole screen the search bar on the top is still maintained and upon dismissal with a swipe gesture down the camera is still running. I am not sure how this affect is achieved. Is it done by using a scroll view or a segue of some kind? Thank you for your help.
Below is the video in question
Snap Chat Camera Roll
Firstly, this type of effect cannot be achieved using the standard camera UIImagePickerController. You will need to create your own camera view.
Here is a good guide to get you started: https://github.com/codepath/ios_guides/wiki/Creating-a-Custom-Camera-View
You could also try using a custom library that can be easily customized such as: https://github.com/omergul/LLSimpleCamera/
Now, in terms of the actual visual, I do not believe there is any actual segue/change of viewcontroller involved. The camera view is probably always on screen (except perhaps when it is fully covered by the Memories screen), it is simply overlayed by other things.
The Memories screen is most likely 'presented' in a custom manner. The show/dismissal logic can be achieved by attaching a UIPanGestureRecognizer to the UIView and translating the view up and down on pan event. If the pan's y value passes a certain threshold up or down, it automatically continues its animation to show or hide the view.
My goal is to create an alert that has three text fields, one taller than the others, and an image that, when tapped, allows the user to choose a picture to replace a set default one.
After unsuccessfully searching for a library for this, I decided to create my own alert by placing a UIView off the screen and, when prompted by a button, would zoom onto the screen; it consists of all the elements I require.
When I run the application, the view pops up correctly, but none of the elements on the view are responding to touch. I've checked that isUserInteractionEnabled for everything is turned on.
What's also odd is that when I keep the view on the screen (instead of placing it some distance away on Storyboard), all the elements work fine.
I'm assuming it had something to do with the animation. I tested it with a fade in instead of a displacement, and the result was the same - the elements were unresponsive.
In order for your elements to be responsive you have to link the action of you clicking them to your view's code. You can do this in a non-programmatic manner by ctrl-clicking your element on story-views and then dragging to the view controller. Then choose action instead of outlet, and choose when the action you want will be triggered (bottom part). Then insert your code in the viewController.
So I figured it out. I used the debug view hierarchy and saw that the alert was behind the elements behind it, even though it was still being shown (for some reason). I changed the zIndex of the UIView and it worked!
I'm making a scene kit app and it all works very nicely indeed. My only annoyance is that for a brief second after loading, my SCNView object is completely blank. I presume that this is because the scene hasn't loaded or rendered yet, but I'd like to avoid it if possible.
I tried putting a masking view mimicking the app's loading screen in front of the SCNView and fading it out once rendering began using renderer:didRenderScene:atTime but alas, the animation for fading out the masking view doesn't happen (it just flashes off immediately instead of fading out). So I put the masking view in the app's main window as an experiment and gave it a short delay. However, even with the delay before removing that mask, the SCNView was still entirely blank for a split second before the scene appeared.
Can anyone tell me how to avoid this annoying graphical artefact?
As usual there is a simple fix that I just failed to find until now. After your scene has been completely set up, simply do:
sceneView.prepareObject(scene, shouldAbortBlock:nil)
...and bingo! No delay. It's caused because scenes, like all objects in a SCNView, are lazily loaded. Calling prepareObject lets you cache them in advance.
One of my views freezes up for several seconds when I tap the back button.
In addition, when I tap on one of the items in this view, it shows a popup (custom, not a UIPopoverController). This popup appears quite fast, but when I "flip" the popup to see it's back side, the same long delay occurs.
I suspect the reason has something to do with the complexity of the view. As you can see in the screenshot below, it's a collection view, it has a background and some of the subviews are rotated (UIViewEdgeAntialiasing is on).
I used the Time Profiler in Instruments to figure out what's going on, but I'm stuck.
I don't see anything useful unless I deselect "Hide System Libraries":
If I look at the method names, I think they are related to auto layout. That suggests that it's trying to render something during the segue. But methods such as cellForItemAtIndexPath are not called.
There is also an iPhone version of this app where I don't experience this problem at all. It uses a tableview in stead of a collectionview. It also has a background and rotated pictures.
I took these measurements using the simulator; on my iPad Mini the situation is worse; it can take up to 20 seconds before the animation starts.
Update - Things I've tried thanks to your answers:
turn off UIViewEdgeAntialiasing : no effect on performance
I think this might be due to the UIViewEdgeAntialiasing flag. It seems that your main view (the one with lots of slightly rotated pictures) have lots of antialiased edges and hence is very taxing on the iPad's GPU. The fact that the drawing performance slows down when your popover is spinning (ie when the background is showing again) gives this some credence.
Try turning it off and see if the performance improves. How does it look like?
Rotation was the bad guy here. Each UICollectionViewCell has a UIView as a container view and within that is a UIImageView. I rotate it like this:
container.transform = CGAffineTransformMakeRotation(M_PI * someRandomFloat);
Remove that line and everything is snappy.
I use the same technique on the iPhone, but apparently this kind of rotation has less of a performance impact in UITableViewCell than in UICollectionViewCell.
I tried subclassing UICollectionViewFlowLayout to rotate cell itself in stead of one subview. Unfortunately that causes a similar performance issue.