Where do you initialize property values in a View Controller? - ios

I have a view controller with properties that determine its behaviour. These are set by its parent in prepareForSegue.
The potential bug this induces in my program is that the parent in question is not guaranteed to set the properties, so I would like to have a default value. On researching, I now understand that properties in Objective C don't have default values. This left me with the following options:
Set the default values for properties in the child view's viewDidLoad method. However, on investigation, viewDidLoad is called after prepareForSegue in the parent - so I would be overwriting the parent's values when the parent actually does set the properties.
I then thought I could use (id) init to initialize the values, but, at least when using storyboards, this method isn't called at all!
I may have a workaround in that objects will initialize to a default value, but in this case all I want to pass in is a BOOL. And since the bool will have some value even if not initialized correctly, I can't test it to see if it is non-nil.
Are there any opportunities for initializing value in the child view controller before prepareForSegue in the parent?

Overriding init will not help as it is not the designated initialiser for UIViewController objects. When manually instantiating a view controller - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle is called, when loaded from a storyboard - (id)initWithCoder:(NSCoder *)decoder will be called. If you want to set properties when the view controller is initialised you have to override both initialisers.
On researching, I now understand that properties in Objective C don't have default values.
They do. nil for objects, 0 for integer values, 0.0 for floating points etc. If you need default values other than that you should set them in the appropriate init method.

Related

When does property value set in Swift class?

Say there is a UIViewController with property
private var counter = 1.
Does this property get its value once when class is loaded into memory or every time viewDidLoad() method calls?
viewDidLoad has nothing to do with initialisation of properties. Property is initialised only once when class is initialised. It is the reason why non-optional properties have to be initialised directly or in constructor.
viewDidLoad is just regular function and even you call it directly, properties stay untouched (if they are not changed in this method).
viewDidLoad is part of lifecycle of ViewControllers and it is called only once when you create the class and load from xib. It is reason why this method is great for initial setup...
viewDidLoad is called only on instanatiation so it's only called once by objected created.
So it's the same.
As just described before :
viewDidLoad usually used for init setup of the ViewController and variables if it's necessary.
deinit usually used to set nil of each ViewController's variable used.

Trouble Initializing a Mutable Array to Add and Remove from Later in Objective C [duplicate]

I have a view controller with properties that determine its behaviour. These are set by its parent in prepareForSegue.
The potential bug this induces in my program is that the parent in question is not guaranteed to set the properties, so I would like to have a default value. On researching, I now understand that properties in Objective C don't have default values. This left me with the following options:
Set the default values for properties in the child view's viewDidLoad method. However, on investigation, viewDidLoad is called after prepareForSegue in the parent - so I would be overwriting the parent's values when the parent actually does set the properties.
I then thought I could use (id) init to initialize the values, but, at least when using storyboards, this method isn't called at all!
I may have a workaround in that objects will initialize to a default value, but in this case all I want to pass in is a BOOL. And since the bool will have some value even if not initialized correctly, I can't test it to see if it is non-nil.
Are there any opportunities for initializing value in the child view controller before prepareForSegue in the parent?
Overriding init will not help as it is not the designated initialiser for UIViewController objects. When manually instantiating a view controller - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle is called, when loaded from a storyboard - (id)initWithCoder:(NSCoder *)decoder will be called. If you want to set properties when the view controller is initialised you have to override both initialisers.
On researching, I now understand that properties in Objective C don't have default values.
They do. nil for objects, 0 for integer values, 0.0 for floating points etc. If you need default values other than that you should set them in the appropriate init method.

Should I use a property or an instance variable in viewDidLoad?

As stated in the title, should I refer to instance variables or the properties in viewDidLoad? I'd assume we should access through properties because "viewDidLoad" means "initialization is done, and all instance variables are initialized to their default values." Is this correct?
To be honest, there really isn't any good reason to not use #property. You get all your getters and setters synthesized for you as well, which is quite nice.
Yeah, all the initialization is already happened in the code. ViewDidLoad can be used for additional initialization.
As per apple documentation:
"If you want to perform any additional initialization of your views, do so in the viewDidLoad method."
I think you might want to expand on your question a little bit more, and go into a little more detail of what exactly it is you're trying to achieve.
Whether you use a class property or an instance variable depends on what you want to do, personally I recommend sticking with #property (Class properties) for anything because they are fundamentally more functional, in terms of: you have getters and setters built for you to use and you don't have to make your own.
because "viewDidLoad" means "initialization is done, and all instance
variables are initialized to their default values
No, viewDidLoad means view is loaded into memory. This is not your viewController's initialization method. Your viewController's init or some method similar does mean initialization is done, and all instance variables are initialized to their default values
So you could use property if you like in viewDidLoad. I will always use it when it's appropriate.

iOS passing property values to initialized views

I have a UIView subclass. The view has a float property. I initialize this subclass from another view (it's superView) like so:
myView = [[CustomView alloc]initWithFrame:aFrame];
The problem is, I am confused about how to assign values to myView's float property. When I try to assign a value just after initializing (from the superview's initWithFrame), nothing happens. Even when I try to to assign from another method or from the viewController it does not work.
Thanks for reading!
Most likely your class is trying to use it in a method that is called before you set it. Make a custom initializer such as -(id)initWithFrame:(CGRect)frame andFloat:(float)f. This will allow you to set the float when the object is created, so it will have that value upon instantiation. If this is not the issue, we will need to see more code!

Is it ok to initialize a class with your own initWithFrame?

I am converting an iPhone app to a Universal app. I have a NIB view which I want to use on the iPad as is but resized and positioned. On the iPhone I am initializing normally with initWithNibName...
EventEditViewController *eventEditViewController = [[EventEditViewController alloc] initWithNibName:#"EventEditViewController" bundle:nil];
I found that this did not work well for me on the iPad for various reasons. So I created my own initialization method to call instead when running on the iPad...
EventEditViewController *eventEditViewControllerForIPad = [[EventEditViewController alloc] initWithFrame:iPadFrame eventDate:longDate event:eventName delegate:self];
This solved a couple of problems. One how to resize and position the view where I wanted it and how to properly initialize certain variables. I am actually passing more variables than you see here.
It works really well, but I just now noticed that, unlike initWithNibName viewDidLoad fires before my initWithFrame method. I only found this out because a variable I was trying to access in viewDidLoad was showing up as a zombie and I thought I was initializing it in my initWithFrame method.
I was surprised by this behavior. Is it normal? It doesn't make sense to me that the view would be loaded before the named initMethod in the alloc/init call.
I am now wondering if what I am doing might not be a good thing. Like I said it works really well, but should I not use my own initialization method here?
If it's ok to do it this way, maybe someone can explain why the view loads before the init method.
Thanks,
John
If your -initWithFrame:... method is accessing the view controller's view property, -viewDidLoad will be called before the init method completes because the view accessor will cause the view to be loaded.
As for whether it's okay to use your own method, it should be fine provided that your init method calls the designated initializer for the class.
Initializing member variables should be done in viewDidLoad or awakeFromNib.
awakeFromNib is the first method that gets called when a view comes to life from a Xib.
It's preferred to use viewDidLoad for allocating memory for huge arrays since you can deallocate them in viewDidUnload.
Both navigation controller and tab bar controller uses view loading methods to unload views when other views demand more memory.
Allocating in anyother methods should be avoided as far as possible.
From Apple's PageControl source code
// load the view nib and initialize the pageNumber ivar
- (id)initWithPageNumber:(int)page
{
if (self = [super initWithNibName:#"MyView" bundle:nil])
{
pageNumber = page;
}
return self;
}
You can have your own custom init method defined in that EventEditViewController and you can use a custom method like above to initialize your viewController and set as many member variables as you want like iPadFrame, longDate, eventName etc in your case.
Just make sure you call it exactly as above as it's important to call super implementation in such custom init methods.
Also just to shed more light on where you should release arrays you created in viewDidLoad method, it's the dealloc method first in addition to viewDidUnload. The reason behind this is viewDidUnload method doesn't always get called. It gets called only when application starts receiving memory warnings. As compared to this, the method dealloc gets automatically called always when you release the initialized viewController and it's retain count reaches 0. You should release the arrays you initialized viewDidLoad method and your other retain properties in dealloc method.
Also keep in mind that when the app receives memory warning, it's actually a chance to free up additional memory. Also the viewDidUnload method gets called for all the viewControllers in memory except visible one at that time.

Resources