property and synthesize : in this code, without "self"? - objective-c

i have a simple question :
if we don't use here the dataController property in another class in the project, we don't really need to use the "#property" and synthesize and we could have just done a simple "=" operation with dataController = controller, like in the second chunk of code? :
DataController *controller = [[DataController alloc] init];
self.dataController = controller;
[controller release];
rootViewController.dataController = dataController;
Second one :
DataController *controller = [[DataController alloc] init];
dataController = controller;
So if we don't need a property outside the class, we could just do it this way?
Thanks

You are correct, if dataController is a retaining property.
If you are just using it once, there is not much to gain with a property. If you change its value often (i.e. assign a different DataController) then even a private property can make sense just to make the memory management easier.

If dataController is not gonna be used in any other class then you don't need to synthesize it. Then Yes, you could just create it inside that class.
(Of course, if your dataController in your rootViewController also need a reference to it, then you need to handle that as well)

Yes, the second example works fine, provided dataController is declared as an iVar and not just a local variable to the method where it is used - but you probably are aware of that.
In both examples you of course need to release the stored value in the dealloc method.

Related

Using an allocated and initialised object outside of viewDidLoad?

I hope the question title is adequate
Just confused about something in a piece of code I have seen in an online tutorial. There is a generic ZHEDog class with declared properties, methods, etc. and from this class we have created several instances - firstDog, secondDog, fourthDog, and so on.
Now, when we created each instance we did so inside of the viewDidLoad method of our main(one)view controller with the line:
ZHEDog *fourthDog = [[ZHEDog alloc] init];
and then we set some of its properties like name, and so on, here after this line.
So we did this instance creation in the view controller's viewDidLoad and so far have not subclassed the generic ZHEDog class, so it is all deriving from the one class file.
Now, where I am confused is that apparently I cannot set a property of this instance in another method (other than viewDidLoad), so I can't say something like:
-(void) printHelloWorld
{
fourthDog.name = "something new";
}
It kind of makes sense but I can't explain why. I would have thought once the instance was allocated and initialised I could change its properties where I wanted to if necessary? But do the same rules of scope apply to viewDidLoad?
Use properties, they are like instance variables accessible from everywhere within the instance of the class
#property ZHEDog *firstDog, *fourthDog;
then instantiate them in viewDidLoad
self.firstDog = [[ZHEDog alloc] init];
self.fourthDog = [[ZHEDog alloc] init];
and change them in a method
-(void) printHelloWorld
{
self.firstDog.name = "woof";
self.fourthDog.name = "something new";
}
What #vadian has is correct, but using properties also allows other classes to see this variable. Say if you imported the header file and it contained #property ZHEDog *firstDog, *fourthDog;. These variables become public. unless they're in the implantation file.
But other approach is creating variables like so:
Header File
#interface ViewController : UIViewController {
ZHEDog *firstDog, *fourthDog;
}
#end
All will be the same expect now the values are private, or exclusive, to just the ViewController. therefore not allowing others to use or see these variables. And to access the variables in your function printHelloWorld:
- (void)printHelloWorld {
firstDog.name = #"woof";
fourthDog.name = #"something new";
}
Allocating
- (void)viewDidLoad {
//new is the combination of alloc and init. only use +new when using alloc and init, not alloc and initWith...
firstDog = [ZHEDog new];
fourthDog = [ZHEDog new];
}
i hope this would better your goal :)

What is the correct way of init iVar variables in presence of ARC

Example iVar foo,
#property (nonatomic) NSString* foo; // inside .h
Option 1
#Synthesize foo; //Inside .m
foo = [[NSString alloc] init]; // viewDidLoad method
Option 2
#Synthesize foo; //Inside .m
self.foo = [[NSString alloc] init]; // viewDidLoad method
Option 3
#Synthesize foo = _foo; //Inside .m
_foo = [[NSString alloc] init]; // viewDidLoad method
Why?
At so many places I have seen code which has different ways of doing init an Object in Obj - C but which one is the best practise?
In this regard, ARC is the same as MRC.
you have specified all these take place in viewDidLoad. in that case, use the setter (Option 2).
if you were to initialize/set in the initializer, then you would use direct access. the basic reason is that in the initializer (e.g. -init), you have a partially initialized object. during initialization, you want to focus on initializing variables your class needs or expects in order to function correctly. as well, you want to avoid side-effects you can encounter when using the accessors in partially constructed states.
in a fully constructed state (e.g. viewDidLoad), you should relegate the implementation to the accessors for correct behavior, as specified by your object's interface.
Additional Reading:
Initializing a property, dot notation
Should I refer to self.property in the init method with ARC?
Why would you use an ivar?
I think you should understand the difference between these three and then decide which one is good for you.
option 1: Here while initializing you are not using the synthesizer method. so there is no use of declaring property-synthesizer in .h and .m
option 2: here you are using property-synthesizer. But the name of the method for accessing the instance and actual instance variable is same.
option 3: Here again you are not using the property-synthesizer method. Here foo is the name of the method and _foo is the actual instance.
In my opinion third one is the good. Since you the difference you can decide which one is good for you.

Lazy instantiation in Objective-C/ iPhone development

Quick question... Well I understand that all properties start out as nil in Objective-C and that sending a message to nil does nothing, therefore you must initialize using [[Class alloc] init]; before sending a message to a newly created property. However, what about if I'm not sending messages to this property or if I set the property using self.property = something? Do I need to alloc init in these cases as well? Also, do UI properties start out as nil as well, such as a UILabel property that you drag out from your storyboard? Do these need alloc init?
Thanks to all who answer
Stunner did a good job of explaining not needing to alloc init objects that have already been created.
But if it is an object that doesn't exist, where are you going to create it? A very common pattern, which I mention because you mentioned it in your post, is lazy instantiation.
So you want an NSMutableArray property. You could alloc init it in some method before you use it, but then you have to worry about "does that method get called before I need my array?" or "am I going to call it again accidentally and re-initialize it."
So a failsafe place to do it is in the property's getter. It gets called every time you access the property.
.h
#property (nonatomic, strong) NSMutableArray* myArray;
.m
#synthesize myArray = _myArray;
- (NSMutableArray*)myArray
{
if (!_myArray) {
_myArray = [[NSMutableArray alloc] initWithCapacity:2];
}
return _myArray;
}
Every time you access that property, it says, "Does myArray exist? If not, create it. If it does, just return what I have."
Plus an added benefit with this design pattern is you aren't creating resources until you need them, versus creating them all at once, say, when your view controller loads or your app launches, which, depending on the requirements, could take a couple seconds.
The reality is when you do self.myProperty = [[Class alloc] init], you're not initializing your property. Rather, you're initializing an object that you tell your property (which is in fact a pointer) to point to. So if you already have an object that's allocated and initialized, you don't have to alloc/init again and you can do self.myProperty = object;
UI Properties do no start as nil, this is because when you add elements in the interface builder, the view owns the elements that you add and these objects are initialized automatically for you. This means if you're creating IBOutlets and connecting them to some properties, you don't have to alloc/init.
I hope this was helpful.
I don't have experience with Storyboards but I know that when you create objects via a xib file all objects are properly instantiated when you tell a view controller to use a xib file. So you need not worry about alloc/initing those objects in code.
Regarding using self.property = <something>, it depends on what something is. If something is any sort of existing object you need not do the alloc init on that object as the self.property = ... syntax calls the property's setter method which will retain, copy, assign, etc. the new value to the property appropriately.
Now any sort of existing object can be an alloc/init'ed object, or an autoreleased object obtained from a convenience method (NSString's stringWithFormat: for example).
As Kaan Dedeoglu pointed out, the self.property = ... syntax points (and retains) the ivar to the object in memory, and it is up to you to initialize that object if it isn't already instantiated.
No you do not need to [[Class alloc]init the properties in your init method.
However, I would encourage you to explicitly set them to Nil in your init method for clarity.

Load custom class properly

I have a custom class which I want to "load" inside the firstViewController and then access it from other classes by segues. My Problem is, I can't even access and change the instance variable inside the firstViewController. Somehow I'm "loading" it wrong. Here is the code I used until now:
inside viewController.h
#property (strong, nonatomic) myClass *newClass;
inside viewController.m
#synthesize newClass;
I then try to access it by:
self.newClass.string = #"myString";
if(newClass.string == #"myString"){
NSLog(#"didn't work");
}
Well, I get "didn't work". Why is that?
When I write
myClass *newClass = [myClass new];
It does work. But the class and its properties gets overwritten every time the ViewController loads again.
What would you recommend? Thank you very much.
Like Kaan said, you forgot to initialize your class, You have only declared and created a pointer for it but not the actual object, on your ViewDidLoad add
self.newClass = [[myClass alloc] init];
It does work. But the class and its properties gets overwritten every
time the ViewController loads again.
That's because every time that specific Viewcontroller loads you are reinitializing the class.
If you want a persistent class through all your program look for the singleton pattern.
This is used in the case when you want to have only 1 instance of a certain object, if you try to initialize another instance of that object you will just receive the one you already have.
PD: newClass.string == #"myString" is wrong.
Use the isEqualToString method when comparing strings.

Retain on NSManagedObject crashes

I'm experiencing a weird problem when trying to use an NSManagedObject subclass. I've got code that looks something like this:
[self.navigationController popViewControllerAnimated:NO];
MyController *myController = [[MyController alloc] init];
myController.managedObject = managedObject;
Pretty simple right? But for some reason it crashes in the synthesized function for setting "managedObject". I tried replacing the function with something like this:
- (void) SetManagedObject:(NSManagedObjectSubClass*) obj
{
if ( managedObject )
[managedObject release];
managedObject = obj;
--> [managedObject retain];
}
And that crashes on the retain call... I'm stumped and don't know where to start debugging this.
There are several problems with your code:
If you provide a custom setter, your property is not a synthesized property (remove SetManagedObject: and use the #synthesized directive instead)
Your custom setter is releasing the object before it retains it. So managedObject might have been freed when you send the retain message (That's the crasher)
SetManagedObject: has the wrong case. Use setManagedObject: if you decide to provide a custom setter.
Don't use NS as prefix for your custom subclasses (NS is used by Apple).
I'd use a synthesized property. Remove your setter code, declare #property(retain) XYManagedObjectSubClass managedObject; in your .h file and use #synthesize in the implementation.