I am working on the iTuneU Stanford iPhone course HelloPoly drawing assignment, and I am getting a call to my object's init routine when I don't expect one. The callback seem to indicate that the call is coming from _loadMainNibFile (after other calls). What I am trying to understand is why is my object being init-ed implicitly. The source files can be found here: -- http://www.cavedrawings.com/hp2_files.zip
Can anyone tell me why the init routine would be called implicitly when loading the NIB file?
Most implementations of initWithCoder: ultimately call another initialization function. It's normal to stack initialization methods when you have a series of them that progressively add information to the initialization process.
_loadMainNibFile calls the initWithCoder: of the file owner of the nib which in turn calls another initialization method which leads up to the final init.
When a nib is loaded all objects within it get instantiated to do any prep work they need to do.
If you want a nib's object loaded and init'd later, put the object in a separate nib and explicitly load that nib when you need it.
Related
I am trying to load a list of assets using the ALAssetsLibrary and enumerateGroupsWithTypes. I populate an NSMutableArrary with the assets loaded so i get to use it later, for instance change a view's background randomly.
I tried to preload this array with the assets in the ViewDidLoad method and only to find out that it gets handled AFTER the view is loaded. if I put a NSLog statement after the load method is called, the log will be printed, but no array initialized until the view is completely loaded.
Question is when should I initialize my array then?
thanks!
The viewDidLoad method does exactly as it suggests - its called once the view is loaded. No surprises there. You could consider loading in the initWithFrame: and/or initWithCoder: methods, depending on which is relevant to you.
Your question doesn't say much about why you want to load something in this method. What's wrong with loading it in, say, the viewDidLoad method and using the array to configure the view before the view will appear? I have no idea how heavy your loading is. But guess what - there's even a handy viewWillAppear: method...!
I have a UIView subclass which currently assembles itself completely programatically. It has a custom initWithFrame:bundle: initializer which is necessary because it uses the bundle passed in to load image resources.
I want to make this view a subview in a larger nib file, but then initWithCoder will be called when the nib loading code gets to it instead of my custom initializer. Is there any way I can place this view in a nib and still have my custom initialization occur?
Yes, you can override initWithCoder: too if your bundle is known ahead of time (read: You don't need it passed in as a parameter). Otherwise, nope.
If you can wait until awakeFromNib, you can do your initialization in there. You still have the problem of not being able to pass the bundle into the method, though. Since awakeFromNib is called after initialization and setup of all outlets and actions, it might be too late for you. Maybe it's better to redesign around the nib-loading system anyway?
When creating a UIViewController derived class in objective-C, what goes into the init method, what should go into loadView and what into viewDidLoad - and more importantly why, and what benefit (performance?) does this have?
Also, how does this relate to UIView derived classes where the only option you have is the init method?
I know the template code already has comments for what goes into each method, but it unclear to me why each thing goes where they say.
Clarification
I would like to know maybe at a lower level, what is the actual difference between things being done in the 'init', 'loadView' and 'viewDidLoad'. What does the framework do in between these calls that may affect the way/time I set up my views and do other work? How are these methods affected by threading?
You want to know some lower-level stuff.
init: This method gets called on ANY NSObject subclass. It is what sets up the object, which you probably already know. In many model (as in the MVC pattern) classes, init is directly used. As for the UIKit classes, very few requires init to be called directly. It should not be used. In the UIViewController, you initialize it using initWithNibNamed:. You can override this method, but in most cases this is not needed. This method is the VERY first method to EVER get called on the class (before any view setup, or such).
loadView:and viewDidLoad: read this article iPhone SDK: what is the difference between loadView and viewDidLoad? .
The only really important thing to know is that -init is the NSObject standard initialization method. -loadView and -viewDidLoad are UIViewController's methods for initialization.
I have an odd problem with UIImagePickerControllerSourceTypeCamera. My application gives the choice to select a pic from the gallery, or take a photo with the camera. If I choose the gallery, I pick a photo and return to my view, no issues.
However, when using UIImagePickerControllerSourceTypeCamera, it appears to do something odd with my view when I return to it.
For example, I have a bunch of code in the viewDidLoad method which moves some objects in the view if it needs to based on some factors - this code gets called when I exit the UIImagePickerControllerSourceTypeCamera, but doesnt get called when I exit the gallery.
Is this expected?
I think your view is getting dumped by the didReceiveMemoryWarning thing which is being triggered by the resource-intensive camera stuff. You can force the simulator to generate a memory warning without the camera to test this theory.
Generally speaking, viewDidLoad needs to be able to deal with getting called multiple times. It's not an init method. It gets called again if self.view gets set to nil and the view later needs to be recreated. There may be a more appropriate place to put any code you have there that's causing problems, but the init methods are tricky because the designated initializer is bypassed by nib loading.
When loaded from a nib, the class's initWithCoder is called instead which bypasses the whole init process because dearchiving is assumed to be sucking in an already-initialized object. Therefore reinitializing the object might break stuff, like call loadView which essentially conflicts with what a nib contains as it's supposed to programmatically construct what the nib already has in it. You can still override initWithCoder as usual though as long as you pass through the args to super like you should, but then this will not get called if you initialize the object with the designated initializer. Of course if you need to worry about that you can put all the code you want executed in both into a method that gets called from both overridden methods.
My tabBarController-based app has several tabs. Each has a custom viewController class, the only difference being the way the instance is initialized. Is there a way to make interface builder send the different tabs custom init parameters?
Currently I'm doing the initialisation in viewWillAppear, but for a bunch of reasons it would make sense to do it in IB instead of in the code.
Any suggestions?
thanks,
Kelso
Interface Builder creates an archive of objects that is unarchived when you program executes. You can't really tell IB to call particular methods.
If you need to initialize before viewWillAppear: is called, you can do so in awakeFromNib, which is guaranteed to be called after all objects have been loaded and all outlets have been connected to their targets.
If you want to do initialization even earlier, you can do so by overriding initWithCoder: (see the NSCoding protocol for documentation). I don't know if it is documented anywhere, but that is the designated initialized for objects being decoded from an archive.
In all of the above, you won't be able to receive parameters, but in the code you should be able to access whatever you need with some judicious use of global variables. You can also use [[UIApplication sharedApplication] delegate] to get access to your application delegate object.
I don't think there's any way to change what methods are called by the IB runtime when your nib is loaded. If you described what you were trying to accomplish (i.e. why doing the setup in viewDidAppear doesn't work for you), you might get a suggestion of a better way to handle your initialization.