Slow down iOS animation to debug? - ios

On OS X, one can hold the shift key to cause animation to slow down. Is there some way to apply this to iOS via a remote debugger or in Instruments?
(Alternatively, I could record in QuickTime and replay frame by frame, but I would rather not have to do that.)
EDIT: I'm looking for a way to do this on the device.

You can slow down animations in your iOS Simulator by clicking Debug-->Toogle Slow Animations in frontmost app.

Temporarily set layer.speed on the view you are animating to a value less than one. For example in my UIViewController subclass, I have a UIView subclass which is animating some changes to it's subviews. If I want to slow down those animations (and only those, not other transitions):
class MyViewController: UIViewController {
private let myView = MyView()
override func viewDidLoad() {
super.viewDidLoad()
// slow down animation speed for only this view
myView.layer.speed = 0.1
}
}
If you want to slow down all animations in your app, set window?.layer.speed, for example in your AppDelegate.
Don't forget to remove this code once you're done perfecting your animation!

Select the simulator and use ⌘T
You will get an output in the console telling you if it's been turned on or off.

Related

UIRefreshControl is flickering and transitions are abrupt

I'd like to set up a UIRefreshControl in my apps' main table view controller to trigger a refresh function to (you probably guessed it by now) refresh it.
Adding it isn't the problem, I'm able to set it up through the storyboard (by enabling refreshing) or in the controller (by using self.refreshControl = UIRefreshControl()).
When it gets triggered by the user it starts refreshing normally, but when I trigger it through self.refreshControl.beginRefreshing() the control isn't displayed in the navigation bar, until I scroll down (like you would normally trigger it)
But that's not even the weirdest part. When it's finally visible to the user there is a constant flicker to it and after a while it's not visible at all.
For the self.refreshControl.endRefreshing() method, the animation is really abrupt any choppy and sometimes the navigation bar doesn't scroll up again (leaving an empty space at the top)
Here is a gif, that should summarise my problem
I use swift 4.2, the application was tested on different simulators (running iOS 12.1) and my iPhone X (running iOS 12.1.2) and the release target is iOS 10.0.
I've already done research on my problem, but no one seems to have the exact issue (at least the flickering) or the solutions don't work for me.
This is how my view controller is set up:
class MyViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.refreshControl = UIRefreshControl()
self.refreshControl?.addTarget(self, action: #selector(reload), for: .valueChanged)
self.refreshControl.beginRefreshing()
}
#objc func reload() {
DispatchQueue(label: "update").async {
sleep(10)
DispatchQueue.main.async {
self.refreshControl?.endRefreshing()
}
}
}
}
Thanks for reading, I really hope someone can help me.
Update
I just discovered that the issue only occurs with a non-translucent navigation bar with large title, so picking a translucent navigation bar instead of the opaque is a solution (sadly not one I would like to live with). Maybe someone has an approach to having a functional refresh control with an opaque navigation bar.
Additionally I submitted a bug report to Apple, because something like that should not happen in the first place, I'll update this post when they get back to me.

Adjusting screen brightness when untouched/touched in iOS with Swift

I am quite new to iOS and Swift to please bear with be while I explain and if anything is unclear let me know and I will explain.
I have an iOS application, it includes some UIImages, UIButtons, etc.. and they interact when touched.
I would like to dim the screen when the application has not been touched (anywhere on the screen) for a while (lets say 10 seconds), and then as soon as a touch is detected anywhere on the UIScreen I would like to increase the brightness again.
I have found that the following line can be used to adjust the screen brightness:
UIScreen.main.brightness = CGFloat(0.5)
but I don't know how to detect a touch anywhere on the screen (without disturbing all the other buttons etc...), and also to combine that with a timer.
(my app is only for a specific purpose, it will not be distributed and it runs only on a iPhone 7 device with iOS10)
Well, there is an API for that purpose.
func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
Returns the farthest descendant of the receiver in the view hierarchy (including itself) that contains a specified point.
This method traverses the view hierarchy by calling the point(inside:with:) method of each subview to determine which subview should receive a touch event. If point(inside:with:) returns true, then the subview’s hierarchy is similarly traversed until the frontmost view containing the specified point is found. If a view does not contain the point, its branch of the view hierarchy is ignored. You rarely need to call this method yourself, but you might override it to hide touch events from subviews.
You need to create the subclass of UIView or UIWindow in which you want to detect touches.
Then override hitTest function and implement required logic inside it.
Update:
See runnable Xcode 8 project to get an idea. Run app and try to press on views and outside of them, you will see logs in debugger console with info about touched view. Hope it will help you.

Can't stop UITableView's scroll movement with another scroll pan if the original movement is too fast

I am using a UITableViewController with custom UITableViewCells. If I scroll relatively slow, the movement can easily be stopped with another small pan or tap. However, if the scrolling is faster, I need to make a much larger movement to reverse the direction of scrolling. Also, stopping it with a tap simply doesn’t work.
I want the default behavior back (like in the Phone app or simply any other application with a long UITableView). What can I do in order to have it again?
func gestureRecognizer(UIGestureRecognizer,shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool {
return false
}
Add Gesturedelegate in your code.
It turned out that my code inside tableView(_:willDisplay:forRowAt:) had a negative impact on the performance of my app. I got rid of the code and this issue went away.

Xcode 8 - Some Views & VCs Not Showing Up on Simulator

The app ran perfectly prior to updating to Xcode 8 Beta 6 and Swift 3. I've changed nothing else but now I have two problems.
First, a few random views are no longer showing up. They're just square, colored boxes. The views above them show up though.
In Interface Builder:
On simulator:
Second, my model VC is no longer appearing when segued. It did before and I can see the segue is being called but now its' not there.
If anyone can provide ideas about either problem it'd be greatly appreciated.
So between Xcode 7/Swift 2 --> Xcode 8/Swift 3, something changed with how to turn a UIView into a circle. Here is my code now:
func roundView (_ viewToRound: UIView) {
viewToRound.layer.cornerRadius = 20
//viewToRound.layer.cornerRadius = (viewToRound.frame.width/2)
viewToRound.clipsToBounds = true
}
As you can see, I've replaced my cornerRadius method to be an explicit "20" instead of inferred from the view size. With my previous "frame.width" the views were literally not showing up at all. Now they're back to normal. I don't know what changed but this definitely fixed it.
Something may have happened to the auto layout constraints. Double check that those are set properly.
Also, you don't need to use the simulator to verify this; use the Assistant editor's Preview view:
As a sanity check, the first thing I would do is reset all of the elements in your view to the suggested constraints to see if that resolves the problem.
It's definitely an AutoLayout issue in Xcode 8. The problem doesn't exist without using AutoLayout. I made this workaround using a protocol:
protocol Roundable {}
extension Roundable where Self: UIView{
func roundCorners(){
self.layer.cornerRadius = self.bounds.height / 2
}
}
class CustomView: UIView, Roundable {
override var bounds: CGRect {
didSet{
roundCorners()
}
}
}
Make the view involved a CustomView and it will show up rounded. I use a protocol here, because in this way it's easy to extend an already existing UIView subclass with the functionality to round the corners. Of course it is possible to set the cornerRadius directly in the bounds property observer.
There is an issue with iOS 10 UIView lifecycle & AutoLayout.
What I mean by that is that in methods such as viewDidLoad & viewWillAppear the frames on all UI elements are `{{0,0},{1000,1000}}.
In cases such as with setting round corners makes rounded corners with 500px & you get invisible UI components :)
How I resolved this issue is by setting the rounded corners in viewDidLayoutSubview in UIViewControllers or layoutSubviews in UIView subclasses.

iOS freezed UI without error logs

I have an issue on my swift iOS app and i'm not able to understand which is the real problem. I have a UITabBarController with five UINavigationControllers on each tab. Main content of these controllers are UICollectionView filled dynamically from a WebService with custom UICollectionViewCells (about 30 for each CollectionView) with custom UIImageViews, custom UILabels and custom UIButtons loaded from custom xib files.
When i push few controllers all is working good (CollectionViews become a bit slower but i think it's normal for memory usage) but when a NavigationController contains 6 or 7 controllers and i try to scroll down, my UI is freezed, the app doesn't crash and i don't receive any kind of runtime error. I can still exit using Home button but the app is completely locked.
I'm dequeuing every cell in every collectionView with identifier and i'm using this attributes in every custom cell for performance:
layer.shouldRasterize = true
layer.rasterizationScale = UIScreen().scale
What i tried
Debug views too see if some UIWindow or UIView is covering the controller view
Stop image loading and show blank imageViews
Clear code used in UICollectionView scroll delegate methods
But the issue is always reproducible on 6th or 7th controller, making some stress test. I gave a look to FPS too, but values are always from 40 to 60 that seems good. CPU usage is always very high, 90/100 % but method didReceiveMemoryWarning is never fired.
My goal would be that my app could push many controllers without freezing or become very very slow, but i can't understand what i'm missing.
Thanks to Philip Mills
Issue is that i was calling this code in my custom UICollectionViewCell setup:
func rotateWithDuration(duration: NSTimeInterval, indeterminate: Bool) {
UIView.animateWithDuration(duration, delay: 0.0, options: .CurveLinear, animations: {
self.transform = CGAffineTransformRotate(self.transform, CGFloat(M_PI))
}, completion: { finished -> Void in
if indeterminate {
self.rotateWithDuration(duration, indeterminate: indeterminate)
}
})
}
View rotation animation was running indefinitely in every cell, so the CPU was a bit sweat.

Resources