I want to understand how to set the parameters of properties (accessors).
I took the following code from an example of Kal calendar.
// Holiday.h
#interface Holiday : NSObject
{
NSDate *date;
NSString *name;
NSString *country;
}
#property (nonatomic, retain, readonly) NSDate *date;
#property (nonatomic, retain, readonly) NSString *name;
#property (nonatomic, retain, readonly) NSString *country;
- (id)initWithName:(NSString *)name country:(NSString *)country date:(NSDate *)date;
#end
// Holiday.m
#import "Holiday.h"
#implementation Holiday
#synthesize date, name, country;
- (id)initWithName:(NSString *)aName country:(NSString *)aCountry date:(NSDate *)aDate
{
if ((self = [super init])) {
name = [aName copy];
country = [aCountry copy];
date = [aDate retain];
}
return self;
}
- (void)dealloc
{
[date release];
[name release];
[country release];
[super dealloc];
}
#end
1) The properties are set to retain, but since the setter can't be used the retain makes no sense here.
2) In addition, in the initWithName method the values are set with copy. Why not directly defining the properties with copy and using the accessor methods?
#property (nonatomic, copy) NSString *name;
// ...
self.name = aName;
3) Do I need the readonly here? I don't know why they are used here. If I would use copy together with the setter the readonly prohibits me to set the value, because there is no setter.
4) In the initWithName method sometimes copy and sometimes retain is used. I would suggest to use always copy here, because the value should not get modified later.
5) What I can remember is that it is OK to copy/retain in the initWithName and release in the dealloc method.
So how would you suggest to use retain, copy and readonly in this example here?
ETA: #DougW correctly points out that a property's ownership type (assign/retain/copy) does not affect the getter. It does still affect the setter. For readonly types, this matters if you are going to override the readonly portion of the declaration in a class extension, so you can use the setter within your implementation. A class extension property override is only allowed to change the readonly status of the property, so the rest of it - which means the atomicity and ownership types - must be declared appropriately in the header. Even if you're not overriding the property now, you might in future, so you might as well document how you want the memory managed for yourself by using the correct option to begin with.
Automatic reference counting (ARC) changes the runtime implementation details by overlaying its own memory management rules on top of the classic refcount rules, but the rules and advice for configuring your properties stay the same.
Why use retain with readonly? If you mark a property as retain, the synthesized accessor does something like this:
/* getter for retain property */
- (NSString *)name {
return [[name retain] autorelease];
}
Now, if the object you sent -name to changes the name while you're still using it, the calling code will still have a valid reference to a string. If you declared it as assign, though, it would be like this:
/* getter for assign property */
- (NSString *)name {
return name;
}
Now, as soon as name is changed by the object, it will have to be released to avoid a leak, which will invalidate the calling code's reference. The retain/copy/assign is really stating a memory-management policy: retain/copy says, "I promise that I hold a reference to the original/a copy of the value I provide here," while assign says, "I just have the value and claim no owning reference to this."
When the value doesn't need memory management, such as a plain int, then assign makes sense. When you're intentionally not retaining an object, such as a delegate, then assign makes sense. But, in most other cases, you'll want retain or copy.
Further, the implementation file can only override the readwrite/readonly portion of a property declaration, not the memory management portion. As declared, the .m file can have:
#interface Holiday (/*class extension*/)
#property(nonatomic, retain, readwrite) NSDate *date;
/* override other properties to make them readwrite... */
#end
Non-public setters for the overridden property declarations will then be synthesized along with the public accessors.
Why not use setters/accessors during -init? Because setters/accessors frequently perform KVO notification, which you want to avoid while your object is not fully initialized, i.e., during -init (when it's half-initialized on its way to full initialization) and -dealloc (when it's half-initialized on its way to being fully un-initialized).
Why use copy with readonly? As in response to your first question: because if copy versus retain versus assign affects both the setters and the getters. A copy getter would look like this:
/* getter for copy property */
- (NSString *)name {
return [[name copy] autorelease];
}
Why sometimes copy and sometimes retain? copy is generally used with value objects (passive objects representing a value); retain is generally used with other objects. Sometimes, efficiency concerns come into play (most likely prematurely...), and you might opt to use retain where you would normally use copy.
How would you use copy/retain along with readonly here? Pretty much as they did. I'd override the declarations in a class extension so I can use setters to change the properties' values outside of -init and -dealloc, where I would only use direct instance variable access. I would also nil out the ivars after releasing them in -dealloc, e.g.,
[name release], name = nil;
This helps avoid sending messages to or otherwise referencing an already-released object.
Related
I have few questions to ask about the following class
#import <Cocoa/Cocoa.h>
#interface SomeObject {
NSString *title;
}
#property (retain) NSString *title;
#end
implementation SomeObject
#synthesize title;
-(id)init {
if (self=[super init])
{
self.title=[NSString stringWithFormat:#"allyouneed"];
}
return self;
}
-(void)testMethod{
self.title=[[NSString alloc] init] ;
}
-(void)dealloc {
self.title=nil;
[super dealloc];
}
In the .h file do we need to declare the title and sub when we add the property. is it not enough to add the #property (retain) NSString *title; line.
2.Do i need to autorelease both assignment to title in the init and testMethod. if So why?
Can some one explain these things to me.
1-
You don't need to declare the iVar in the header. You might also use
#synthesize myVar = _myVar;
if you want to go for a different iVar name
2-
Declaring a property "retain" means that every time you assign the property with a new object, it automatically releases the previous object and retain the new one.
Therefore, if you use a convenience method like stringwithFormat, the property will retain that object for you.
If you want to use alloc-init, for me the best way to do is:
NSString *str = [NSString alloc] init];
self.title = str;
[str release];
Besides, it is right to assign nil to the property in the dealloc because the property will release the object it has, and it calls retain on nil which doesn't do anything
1.No need to declare title in .h, declaring property is enough.
2.when you are using self.title in init, you do not have to autorelease it.But when you initialize it in testMethod, you need to autorelease it because you have declare the property as retain.And do not forget to release title in dealloc.
you don't need to add as it is done automatically (Since Xcode 4 I guess).
in init- you don't as it already returns an autoreleased object..
where as in testMethod you need to since you are allocating it..
you always have to release any object which you create using alloc , copy or new .... AMEN.. :)
Be aware it is not considered a good practice to use accessor methods in initializer methods and dealloc method. Do check out this answer: Why shouldn't I use Objective C 2.0 accessors in init/dealloc?
Also in Apple's memory management guide: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html
So what i want to ask is below
Here is my header file
NSString *myString;
In the m. file
-(void)someMethod{
myString = [NSString stringWithString = #"Hello"];
NSLog(#"%#",myString);
}
-(void)dealloc{
[myString release];
}
-(void)viewDidUnload{
[myString release];
myString=nil;
}
Ok now the other situation
In my header file
NSString *myString;
#property (nonatomic,retain) NSString *myString;
In the m. file
#synthesize myString;
-(void)someMethod{
NSString *tempString = [[NSString alloc] initWithString:#"Hello"];
self.myString = tempString;
[tempString release];
NSLog(#"%#",myString);
}
-(void)dealloc{
[myString release];
}
-(void)viewDidUnload{
[myString release];
self.myString=nil;
}
I really need an idiot guide for this cause I do not understant it yet. Both works. Also am i using the release in dealloc and viewDidUnload correct?? Thank you in advance
Info about properties, not a definitive guide:
One advantage of #property is that with #synthesize they create setters and getters that handle the retain and releases (as applicable) and work the with or without ARC (with minor modifications).
properties no longer need their associated ivars to be declared, they will be automatically generated.
properties can be placed in the header file (.h) for public use or in the implementation file (.m) in a class extension for private use in the class.
#property and #synthesize statements have nothing to do with allowing "dot notation". "dot notation" can be viewed as a substitution for the bracket form of accessing a setters and getters (actually use is more general but use is best restricted to getter/setters).
[self myIvar] is equivalent to self.myIvar and [self setMyIvar:myValue] is equivalent to self.myIvar = myValue.
dot notation can be used on non-properties such as NSStrings: myString.length works fine and is reasonably acceptable usage.
dot notation has nothing to do with properties however Xcode will only offer auto completions for properties.
#property and #synthesize provides the getter and setter (accessors) methods rather than you having to write it out yourself. The declaration is made with #property and it is implemented with #synthesize.
So in the main program when you create a new class object (Assuming your class is called MyClass with MyClass.m, MyClass.h), you are able to access your string variable myString using the dot operator. If your object is called NewObject, then you can access the string inside the main program with NewObject.MyString.
You can also use this to set a value for string (i.e. NewObject.MyString = OtherString). Very handy and time-saving. They both work because you are accessing the variables from within the class and so you wouldn't need to set the accessors.
For the -(void)dealloc you also need [super dealloc] inside there to release the variables of the superclass. You don't need to release MyString in viewDidUnload as you have done it in the -(void)dealloc method.
When you allocate memory in -(void)viewDidLoad, then you would need to release it in -(void)viewDidUnload, but you haven't here so it isn't needed.
In this example:
#interface something : something
{
NSString *saveString;
}
-(void)saveStringForLater:(NSString*)myString
{
//do stuff with myString
...
//then save it for later
saveString = myString;
}
-(void)someOtherTimeInFuture
{
//do stuff with saveString
...
}
So given the above, my questions are:
1) Is this safe/proper way of doing this?
2) Will I need to worry about releasing saveString?
3) Should I be copying the string instead of just saving the pointer?
Excuse my ignorance as I am fairly new to Obj-C but have a C++ and C# background.
Thanks!
This is what #properties are for. They manage getter and setter code for you, so you don't have to think about these questions.
.h
#interface MyClass : NSObject
{
NSString *myString;
}
#property (nonatomic, retain) NSString *myString;
#end
.m
#implementation MyClass
#synthesize myString;
-(void)dealloc
{
[myString release];
[super dealloc];
}
#end
With those things in place, you can now talk about self.myString and not worry about memory. When you assign to it it'll do a retain. If you assign again, it'll release the first object and retain the new one. And then it'll stick around retained until your viewcontroller unloads.
You can by all means accomplish this same end with an iVar (which is what you're doing in your code sample), but then memory management is yours to handle, and it can be a bit fiddly. Best to use the #property system to create appropriately memory-managing setter code.
You have 3 optins,
Copy - should be using if the string can change or when getting called from a code you have on control of like third party
Retain - will increase the reference count to the object and will prevent destruction of it
In both these options you have to release it when you done with it
Last you can define a property with retain,copy attribute - this will let the system worry about managing it and probably the best option in most cases
What is the preferred and/or correct way to release an NSMutableString (or any other class for that matter) instance and assign a new instance to the same variable in Objective-C on the iPhone?
Currently I'm using
[current release];
current = [NSMutableString new];
but I understand that the following works, too.
NSMutableString *new = [NSMutableString new];
[current release];
current = [new retain];
[new release];
The variable current is declared in the interface definition of my class and gets released in dealloc.
Both versions should work equally well. Which means I'd go with the first one - fewer lines of code.
If you're thinking about handling instance variable I'd suggest using property for that - in you class interface declare:
// MyClass.h
#interface MyClass {
NSMutableString* current;
}
#property (nonatomic, retain) NSMutableString* current;
#end
And then let compiler generate setter and getter methods for you automatically with desired memory management behaviour:
// MyClass.m
#implementation MyClass
#synthesize current; // Tell compiler to generate accessor methods
...
The generated setter method will release previous "current" value and retain the new one. You'll still need release it in your dealloc method.
To access you variable via property you should use .:
self.current = [NSMutableString string];
This is equivalent to calling [self setString:[NSMutableString string]] (setString method will be generated automatically).
Also as you're dealing with mutable string here it may be worthwhile to use copy atribute for property instead of retain.
What do #synthesize and #property do in Xcode? Please provide an explanation in really simple terms?
You asked for simple terms:
#property declares a property in your
class header
#property (nonatomic, retain) NSString *myString;
#synthesize creates your setter and
getter for your property (accessor
methods)
Without synthesize you have to write
your own setter and getter
implemention, like getMyString or
setMyString (capitalize the first
character of your property)
Sam: Just an advice: http://www.cocoadevcentral.com/d/learn_objectivec/ is a pretty solid resource to learn about basics like properties.
Good Luck!
Properties and synthesized accessors are new features in Objective-C 2.0.
When you declare a #property you declare somewhat an instance var. Then you #synthesize accessor methods (i.e. getter and setter) for that property.
There are also #dynamic accessors if you're interested.
You should really do your homework on this. Apple has nifty pdf for that.
Think of all objective-c magic as just a "smarter macro", like a "smarter #define statement"
#property if you notice is always in the h file,
#synthesize is always in the m file.
So in the background
#property (whatever) NSString *myString;
becomes a declaration of 2 methods and a private variable;
void set_myString:(NSString *) str;
(NSString*) get_myString;
declarations in the header file
to make them do something their implementation is added into m file when you type in
#synthesize myString;
which becomes something like
void set_myString:(NSString *)str
{
myString = str;
}
(NSString *) get_myString
{
return (myString);
}
But it's smarter than this
depending on if you say "retain" "strong" or "weak"
it will either just return the pointer to the myString or it will copy the myString into a new object
So all of this is done automatically by a compiler just by reading your declarations.
Which is quite useful and saves a lot of time
By default all our variables are Private so we can't acess out of the class.
if we want to use our instance variable in out of the class.
When you declare a #property you declare somewhat an instance var. Then you #synthesize accessor methods (i.e. getter and setter) for that property.
There are also #dynamic accessors if you're interested.
it simply sets the property's setter variable name in it's own class.
For example lets say I have this: #property (nonatomic, copy) NSArray* viewControllers;
Well if i want to access the setter _viewController i wouldn't set a synthesize variable.
but if i want to access the viewController variable by the name viewController instead of _viewController, I would do #synthesize viewController;.
If I wanted to use it as a completely different name I could do this #synthesize viewControllers = viewControlololer; but that's only setter. As you will notice [self viewControllers] only works and not [self viewControlololer];
So I don't understant why everyone writes sets the "setter and getter" of a property. It doesn't change the getter variable at all... unless that means [self viewController] is aware of viewControlololer (obviously).
Actually properties are synthesized, either implicitly or explicitly. Properties are implicitly synthesized. So there's no need to use synthesized unless you wanna change the name of the variable to something different than _property_name.
There are other use cases, for example if you don't want an instance variable to back your property.
Properties are explicitly synthesized by using the #synthesized directive.
(Answer extracted from the Big Nerd Ranch guide)