Layout issues in iOS10 - swift

I'll try to keep this short.
I was using viewDidLayoutSubviews to (mostly) apply corner radius to some views in several UIViewControllers.
Also doing the same in layoutSubviews for custom UIViews.
After installing Xcode 8 Beta, this stopped behaving predictably.
Some times it works, others works with a delay, others still, not at all...
The one thing that was immediate while debugging was that on first call of viewDidLayoutSubviews, bounds are zero for the views in question.
On second call, the bounds are correct; the thing is, as I said, the second call either has a (visible) delay, or never happens at all.
Any pointers?
Thank you all in advance.
Best,
Renato.

Answering my own question, just in case someone bumps into the same issue...
As far as I can tell, in iOS 10 you cannot assume calls performed on layoutSubviews, viewDidLayoutSubviews, etc. will be called on the main thread.
So the answer seems to be simply wrapping the UI calls on a dispatch block (new iOS 10 sintax):
DispatchQueue.main.async {
// Do UI stuff here...
}
Hope it is helpful for someone :)
Best regards,
Renato.

Related

How can I optimize my controllers so they load faster?

Most of the iOS apps I use are very responsive, when I tap on an element it goes to the next view right away. In my app, some of my view controllers take 0.5-1.0 second to load.
My code is all in the viewDidLoad method and I'm pretty sure that's the problem but I can't move anything out since I need every single element that I instantiate.
A solution I thought is to move all the work I do in viewDidLoad in a thread then call the main thread when I'm ready to call addSubview, would that work even if UIKit is not thread safe? Or is there something else I'm missing?
Try to move some code you might have in viewDidLoad to viewdidAppear. viewDidAppear is being called once the view is presented. If you have to make some hard work, do it there and maybe show aa spinner somewhere while you do that.
What are you exactly doing in viewDidLoad? Btw remember that a view is only loaded when you need it, if you want to switch between views faster I can suggest you to create an initializion phase where you call -view on all the view controller you want to show, maybe helped with a spinner or a progress bar. but pay attention this would work only with intensive loading task and not memory consuming tasks. It sounds very strange your request, so is better the you try to explain better why your viewDidLoad is so slow, maybe there is something wrong.
Define your UI elements in Xcode as part of designing the interface. That way, Xcode can compile your storeyboard or xib files into the rapidly loading binary form.

viewWillAppear / viewWillDisappear not called....my answer to this

I have been struggling with this issue for a while and i noticed that many people came across the same thing by reading many posts here and on other forums. Just this morning i realised what i was doing wrong and i thought of sharing it just in case someone stumbles over it in the future.
the problem in my implementation was that within viewDidLoad of view controller (VC1) i was setting its view property to a new view controller (VC2) which forces i believe the framework to exit viewDidLoad of VC1 without reaching its end, hence not calling the consequent delegate function of the view controller: viewWillAppear, viewWillDisappear, viewWillAppear, and viewWillDisappear!
So my solution was to delay all the code that has to do with creating and setting VC2 to be called from within viewDidAppear instead of viewDidLoad. If you do it from viewWillAppear you will get to the same trouble.
Hope it helps
AF
Why would you go to all this bother just to save the memory of a UIViewController?
sizeof(UIViewController) gives 132 bytes. Even knowing that a view controller will create a fair few support objects so it's going to take up more memory than that this is a fantastic example of premature optimization.
I'd give it a fair chance that the code solution you have gone for will :
(a) leak memory in edge cases
(b) fail on further updates to iOS
(c) be a nightmare to debug by any coder other than yourself
(d) be a nightmare to debug by yourself in more than a few weeks
Why not just write your app using the frameworks provided and profile it - if this tiny amount of memory is causing you problems the fine, implement your solution. If not, leave well alone.

CS193P - Assignment 3 - drawRect get called only on the first setNeedsDisplay

I'm taking CS193P iPhone Development courses, and even if.. I know that I'm pretty late
comparing to Stanford's students, I'm doing Assignment 3.
My current problem is: My drawRect method does not get called on every
setNeedsDisplay... but only on the first.
Also, what I noted is that my polygon object is NULL (from
PolygonView).
Here are the sources of my project:
PolygonShape.h
http://pastie.org/855503
PolygonShape.m
http://pastie.org/855507
Controller.h
http://pastie.org/855508
Controller.m
http://pastie.org/855509
PolygonView.h
http://pastie.org/855511
PolygonView.m
http://pastie.org/855513
If someone could help me.. I guess this is pretty simple but I can't
seem to find it!
Thanks a LOT! :)
drawRect: is not necessarily called on every setNeedsDisplay.
Calling setNeedsDisplay only clear the cache of the view's layer. drawRect: will be called only when the screen is actually refreshed. So before the runloop resumes calling setNeedsDisplay multiple times may not have any effects.

How to correctly remove view from it's superview if no longer needed?

Apple says:
removeFromSuperview Unlinks the
receiver from its superview and its
window, and removes it from the
responder chain.
(void)removeFromSuperview
Never invoke this method while
displaying.
So before I call that, I should call setHidden:YES? Would that be enough?
That warning is there so that you don't call removeFromSuperview from within a drawRect: method. The Cocoa runtime makes extensive use of the view hierarchy during drawing operations, so removing a view from its superview while drawing can really screw things up.
Calling removeFromSuperview at any other time is perfectly fine, and there is no need to hide the view prior to removing it.
Wow. I've never seen that note in the docs before and I just got a little scared about some code I've written :)
http://www.iphonedevsdk.com/forum/iphone-sdk-development/9729-curious-thing-removefromsuperview-doc.html
The consensus is that it's a poorly worded sentence and you should not invoke this method while in the process of displaying/drawing something. But if it's currently displayed, then it's ok.
I'd really recommend asking Apple for guidance on this one though.

Flip transition takes time

I am using the example from TheElements sample code provided with the iPhone SDK to achieve flip transition between 2 views. The transition from the 1st view to the second is not as responsive as the one from second to first. I am not sure why this is happening. The transition does happen but takes almost double the time it should.
I tired comparing my code with the one in TheElements and don't see much difference in the transition portion. Any ideas?
Thanks.
It could be any number of things, but I suggest you start with your viewWillAppear: and viewDidAppear: methods as well as viewWillDisappear: and viewDidDisappear:.
You're most likely doing something rather processor intensive that's causing the slowdown.