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.
Related
Let say i have an class named as MyTestClass.h.
Class structure is look like
#interface MyTestClass : NSObject {
NSString *testString;
}
#property (nonatomic, retain)NSString * testString;
#end
.m file
#implementation MyTestClass
#synthesize testString;
-(id) init{
[self setTestString:#""];
return self;
}
-(void)dealloc{
[self.testString release];
testString = nil;
[super dealloc];
}
#end
Now i created an object of MyTestClass and assigned testString twice
MyTestClass * myTestClass = [[MyTestClass alloc] init];
[myTestClass setTestString:#"Hi"];
[myTestClass setTestString:#"Hello"];
Now i think, two times my testStrings memory is leaked!! (one through init() and another one through my first setTestString method)
Am i correct? or will #property (nonatomic, retain) handle/release previous allocated memory?
or ,in this kind of cases ,will i need to override the setTestString() in MyTestClass.m like below code
-(void)setTestString:(NSString *)tempString{
[testString release];
testString = nil;
testString = [tempString retain];
}
Any help on this question is appreciated.
Thanks.
Any help on this question is appreciated.
I'll take this as a licence to make sone observations not necessarily directly related to your question.
Firstly, if you declare a retain property (as you have done) and synthesize it, the automatically generated getters and setters handle memory management correctly for you.
If you manually create setter (which you are allowed to do even with an #synthesize existing), you have to do the memory management yourself. Use either of trojanfoe's examples.
The setter in your question contains a bug in that if testString == tempString i.e. you assign the value of the property to itself, you could end up with assigning a dangling pointer to the property because you effectively release tempString and then retain it.
This is an implementation detail that you an safely ignore, but string literals e.g. #"blah" are compiled into the executable and will never be deallocated no matter how many times they are released. So, with your example, even if the setter did not do correct memory management, there will be no leak.
By the way, the normal pattern for an init method is
-(id) init
{
self = [super init];
if (self != nil)
{
// init stuff
}
return self;
}
or logical equivalent.
You should get into the habit of using it because you need to call the super class's init method and it is allowed to change the value of self, even to nil.
Also, while it is very good practice normally to set the object reference to nil after releasing it, in both cases when you do it, it is unnecessary. the first time, the variable is about to go out of scope and the second time you immediately assign it from some other object.
It's not a leak. Synthesized variable are correctly handled.
A synthesized method is implemented in this way (for a retain keyword)
#property (nonatomic, retain) NSString *string;
//backed by variable NSString *_string;
- (void)setString:(NSString*)newString
{
if (newString != _string) {
[_string release];
_string = [newString retain];
}
}
Of course this is a leak:
- (void)aMethod //of my class with string property
{
NSString *aString = [[NSString alloc] initWithString:#"hello"];
self.string = aString; //retain count of 2
self.string = #"hello2"; //retain count of 1 for aString
//now I don't release aString.... leak
}
If you use the auto-generated setter (in your case, setTestString:, which is also called by self.testString = ...;), the previous value of a retain property is released before being set. So no, there is no leak in the code you posted above.
The synthesized setter method should do the right thing. Here's an example of it's implementation:
- (void)setTestString:(NSString *)tempString
{
[tempString retain];
[testString release];
testString = tempString;
}
or:
- (void)setTestString:(NSString *)tempString
{
if (tempString != testString)
{
[testString release];
[tempString retain];
testString = tempString;
}
}
the dealloc is only called when the instance is destructed.
if you do :
[myTestClass setTestString:#"Hi"];
[myTestClass setTestString:#"Hello"];
in the same block, you're juste calling twice the setter. there is no memory leak.
When you use #synthesize on a property that specifies retain, the setter that's generated will handle the retain/release correctly for multiple assignments. As long as you use self. rather than going directly to the backing variable and do a final release in dealloc you should be fine.
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
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.
When do you have to use #property and #synthesize in the iPhone SDK? And why use #property and #synthesize?
I was studying property, but I can't get a correct idea. What would some examples for illustrating this be?
#property : you used it when you want to:
You can use some of the really useful generated code like nonatomic, atmoic, retain without writing any lines of code. You also have getter and setter methods. To use this, you have 2 other ways: #synthesize or #dynamic: #synthesize, compiler will generate the getter and setter automatically for you, #dynamic: you have to write them yourself.
#property is really good for memory management, for example: retain.
How can you do retain without #property?
if (_variable != object) {
[_variable release];
_variable = nil;
_variable = [object retain];
}
How can you use it with #property?
self.variable = object;
When you are calling the above line, you actually call the setter like [self setVariable:object] and then the generated setter will do its job
#property (along with #synthesize) automatically generates set and/or get code. So the following code:
self.prop = #"some string";
is equivalent to
[self setProp: #"some string"];
Note also,
self.prop = #"some string";
is different from
prop = #"some string";
The latter sets the variable directly, whereas the former calls the method getProp to set the variable prop.
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.