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

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.

Related

Layout issues in iOS10

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.

Is there a leak in the Scroll View Suite sample code by Apple?

I need help with the code from Apple's ScrollViewSuite; specifically I'm looking at the ThumbImageView class, which doesn't have a dealloc method defined. I see in the .h that the property for imageName uses retain.
(I wasn't sure if I was allowed to post any code since it's Apple's, so please let me know if I can/should.)
Anyway, I thought if we use "retain" that we are responsible for releasing the object reference.
The method CreateThumbScrollViewIfNecessary (from the RootViewController implementation file) has a for loop which allocs ThumbImageViews, sets the delegate, and then after adding the thumbview as a subview the a scrollview, proceeds to release the thumbview. If these objects are actually being released, how does the delegate do its job notifying when an image has been tapped, scrolled, etc.
Sorry I'm just so confused. Any help would be greatly appreciated.
The code leaks. Unfortunately, Apple’s sample code usually leaves a lot to be desired, the design often sucks and there are leaks and glitches. It’s best to take it only as an annotated API reference that shows how various parts of the API fit together, nothing more.
You are responsible for clearing the object reference. As far as I can tell, that code of Apple's would leak if that property were ever assigned a value.
Any view retains its subviews. After each view has been added to the scrollview, the class that creates it has no more use for it so it releases its reference. The object won't actually be deallocated until the scrollview also releases its reference, so the views remain "live" and able to signal their delegates until that happens.

iPhone: how to load objects *after* the main viewcontroller has appeared

Ok hopefully this is an easy question:
I have a main viewcontroller that is loaded by the app delegate at application startup.
This viewcontroller has some code in 'viewDidLoad' to create some non view type based objects (some sound/data objects). Aside from that it also loads a UIView.
The sound/data objects take a while to create, but the app is quite functional without them for a start - so I want to load these objects after the UIView has loaded, but can't seem to figure out how.
I have tried moving the appropriate code to viewDidAppear, but this is still called before the UIView actually appears on screen. Is there a function that is called after the viewcontroller actually starts displaying UIViews, or any other way to achieve what I want?
Any help would be much appreciated - thanks!
In case anyone else has a similar problem, I found a way to solve it: use NSThread to load things in the background without pausing everything else.
There's a good simple example here: http://www.iphoneexamples.com/.

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.

Trick to getting initWithNibFile to be invoked?

I've implemented a View Controller, and I'm trying to do some very basic initialization in initWithNibFile...which I understand to be the designated initializer for View Controller objects.
I've tried to put breakpoints on the code, and have put very simple NSLog statements into it as well. Regardless...I'm not seeing it be executed (and the object i'm attempting to alloc/init inside the function is also not being allocated - so I'm about 99% sure I'm not hitting the code.
Is there something I need to do elsewhere to cause this method to be invoked?
I'm getting a clean build, no warnings or errors. And the app successfully loads up the View, and I can invoke a ButtonClick method I've coded and connected to this same View Controller.
Any suggestions would be appreciated.
TC
I ended up moving my allocation logic to viewDidLoad, and that works fine.
Not sure why the initWithNibFile was not working...but I'll take the small victory !!!
Thanks for offering to look at the code bpapa.
You probably need initWithCoder: It's what the SDK uses to read from nib files during startup.
initWithNibFile: is almost never called by the system. Usually you call this manually. The documentation is quite misleading on this point.
In any case, be careful doing too much initialization in the initWithXXXX methods. The view's targets and actions aren't likely to be set up and connected yet. viewDidLoad is almost always the right place to do viewController setup anyways.