Deallocating nonatomic copy setter - objective-c

I am trying to create non-atomic copy accessors, and I read everywhere that the object should be released at the end. So, if you could help me understand whether I am doing it properly, I would appreciate it. Will the following be correct?
#interface ClassA: NSObject
{
NSString* stringA;
}
#property (nonatomic, copy) NSString* stringA;
#implementation ClassA
#synthesize stringA;
-(void) setStringA: (NSString*) stringInput {
if(stringA != stringInput) {
[stringA release];
stringA = [stringInput copy];
}
}
-(void) dealloc {
[stringA release];
[super dealloc];
}
I am looking for a confirmation whether I need to deallocate stringA in the dealloc method at the end and whether I did it correctly.
Many thanks.

You need to release it, yes. (You don't deallocate things. You release your ownership of them and they may be deallocated as a result.)
Your code is correct.
The rules are that you must release any object you receive from a method whose name begins with "alloc" or "new" or contains "copy". You also must release any object that you retain. Since you call -copy on stringInput, you are responsible for eventually releasing the object you receive from that.

#Ken Thomases is right; your code is correct. A few things, though:
You don't really need to declare the ivar, or synthesize the property, or write your own setter; all this is done for you. So your code (while correct) could be simplified to:
#interface ClassA: NSObject
#property (nonatomic, copy) NSString* stringA;
#end
#implementation ClassA
-(void) dealloc {
[_stringA release];
[super dealloc];
}
#end
Second, if you're using ARC (which I recommend), the code can be simplified even further (by removing the dealloc override completely).
#interface ClassA: NSObject
#property (nonatomic, copy) NSString* stringA;
#end
#implementation ClassA
#end
In this case stringA is released by your class on dealloc, but you don't have to write code to do that; ARC does it for you.

Related

How to reference member variable in the implementation file

I am learning Objective-C and I am trying to split the class definition from the implementation as shown below.
Now in the code I want to reference the both of:
NSString *CarMotorCode;
NSString *CarChassisCode;
In the implementation file. I attempted to use:
self.CarMotorCode;
self.CarChassisCode;
But it does not work. Would you please let me know how to reference it.
Note: please let me know what is the right naming convention for the variables enclosed inside the brackets in the implementation section? Are they member variables?
Car2.m:
#import <Foundation/Foundation.h>
#import "Car2.h"
#implementation Car2
-(id) initWithMotorValue:(NSString *)motorCode andChassingValue:(NSInteger)ChassisCode {
self
}
#end
Car2.h
#ifndef Car2_h
#define Car2_h
#interface Car2 : NSObject {
NSString *CarMotorCode;
NSString *CarChassisCode;
}
-(id) initWithMotorValue: (NSString *) motorCode andChassingValue: (NSInteger) ChassisCode;
-(void) startCar;
-(void) stopCrar;
#end
#endif /* Car2_h */
You have declared instance variables (ivars). To get the “dot syntax”, you need to declare properties. The “dot syntax” is syntactic sugar that makes use of the “accessor methods” that are synthesized for you when you declare a property. (FWIW, it’s advised to not declare ivars manually, anyway, and rather to declare properties and let the compiler synthesize the necessary ivars. See Programming with Objective-C: Properties Control Access to an Object’s Values and Practical Memory Management: Use Accessor Methods to Make Memory Management Easier.)
Thus:
#interface Car2: NSObject
#property (nonatomic, copy) NSString *motorCode;
#property (nonatomic, copy) NSString *chassisCode;
- (id)initWithMotorCode:(NSString *)motorCode chassisCode:(NSString *)chassisCode;
#end
And your init method might look like:
#implementation Car2
- (id)initWithMotorCode:(NSString *)motorCode chassisCode:(NSString *)chassisCode {
if ((self = [super init])) {
_motorCode = [motorCode copy];
_chassisCode = [chassisCode copy];
}
return self;
}
#end
That will synthesize ivars _motorCode and _chassisCode for you behind the scenes, but you generally wouldn’t interact directly with them (except in init method, in which case you should avoid accessing properties). But in the rest of your instance methods, you could just use the properties self.motorCode and self.chassisCode.
A few unrelated notes:
I dropped the car prefix in your property names. It seems redundant to include that prefix when dealing with a car object.
I start my property names with lowercase letter as a matter of convention.
I changed the init method signature to better mirror the property names (e.g. not initWithMotorValue but rather initWithMotorCode).
Alternatively, you might use the strong memory qualifier rather than copy. E.g.
#interface Car2: NSObject
#property (nonatomic, strong) NSString *motorCode;
#property (nonatomic, strong) NSString *chassisCode;
- (id)initWithMotorCode:(NSString *)motorCode chassisCode:(NSString *)chassisCode;
#end
And
- (id)initWithMotorCode:(NSString *)motorCode chassisCode:(NSString *)chassisCode {
if ((self = [super init])) {
_motorCode = motorCode;
_chassisCode = chassisCode;
}
return self;
}
But we often use copy to protect us against someone passing a NSMutableString as one of these properties and then mutating it behind our back. But this is up to you.
You defined chassisCode to be a string in your ivar declaration, but as an NSInteger in your init method signature. Obviously, if it’s an NSInteger, change both accordingly:
#interface Car2: NSObject
#property (nonatomic, copy) NSString *motorCode;
#property (nonatomic) NSInteger chassisCode;
- (id) initWithMotorCode:(NSString *)motorCode chassisCode:(NSInteger)chassisCode;
#end
and
- (id)initWithMotorCode:(NSString *)motorCode chassisCode:(NSInteger)chassisCode {
if ((self = [super init])) {
_motorCode = [motorCode copy];
_chassisCode = chassisCode;
}
return self;
}
If you’re wondering why I didn’t use the property accessor methods in the init method, please see Practical Memory Management: Don’t Use Accessor Methods in Initializer Methods and dealloc.

NSArray #property backed by a NSMutableArray

I've defined a class where I'd like a public property to appear as though it is backed by an NSArray. That is simple enough, but in my case the actual backing ivar is an NSMutableArray:
#interface Foo
{
NSMutableArray* array;
}
#property (nonatomic, retain) NSArray* array;
#end
In my implementation file (*.m) I #synthesize the property but I immediately run into warnings because using self.words is the same as trying to modifying an NSArray.
What is the correct way to do this?
Thanks!
I would declare a readonly NSArray in your header and override the getter for that array to return a copy of a private NSMutableArray declared in your implementation. Consider the following.
Foo.h
#interface Foo
#property (nonatomic, retain, readonly) NSArray *array;
#end
Foo.m
#interface Foo ()
#property (nonatomic, retain) NSMutableArray *mutableArray
#end
#pragma mark -
#implementation Foo
#synthesize mutableArray;
- (NSArray *)array
{
return [[self.mutableArray copy] autorelease];
}
#end
Basically, put the NSArray property in a category in your header file and the NSMutableArray property in the class extension in your implementation file. Like so...
Foo.h:
#interface Foo
#end
#interface Foo (Collections)
#property (nonatomic, readonly, strong) NSArray *someArray;
#end
Foo.m
#interface Foo ()
#property (nonatomic, readwrite, strong) NSMutableArray *someArray;
#end
Simple:
1) Don't use a property when it ain't one.
2) Code simplifies to:
- (NSArray *)currentArray {
return [NSArray arraywithArray:mutableArray]; // need the arrayWithArray - otherwise the caller could be in for surprise when the supposedly unchanging array changes while he is using it.
}
- (void)setArray:(NSArray *)array {
[mutableArray setArray:array];
}
When the object is alloced create the array, when it dies, dealloc the array.
When large effects happen at the mere use of a '.' operator, its easy to overlook hugely inefficient code. Accessors are just that. Also - if someone calls aFoo.array - the contract is to get access to foo's array members - but really its just a copy at the time of the call. The difference is real enough that it caused bugs in the other implentations posted here.
Update: this answer is not valid anymore. Use one of suggested solutions below.
These days you can do the following:
Foo.m:
#implementation Foo {
NSMutableArray* _array;
}
#end
Foo.h:
#interface Foo
#property (readonly, strong) NSArray* array;
#end
You can still address mutable _array by ivar from the inside of implementation and outside it will be accessible via immutable property. Unfortunately this doesn't guarantee that others can't cast it to NSMutableArray and modify. For better protection from idiots you must define accessor method and return immutable copy, however that might be very expensive in some cases.
I would actually agree with one of the comments above that it's better to use simple accessor methods if you need to return some read-only data, it's definitely less ambiguous.
That's because your property must match the actual ivar's class type.
A possible solution/workaround:
//Foo.h:
#interface Foo
{
NSMutableArray* mutableArray;
}
#property (readwrite, nonatomic, retain) NSArray* array;
//or manual accessor declarations, in case you're picky about wrapper-properties.
#end
//Foo.m:
#interface Foo ()
#property (readwrite, nonatomic, retain) NSMutableArray* mutableArray;
#end
#implementation
#synthesize mutableArray;
#dynamic array;
- (NSArray *)array {
return [NSArray arrayWithArray:self.mutableArray];
}
- (void)setArray:(NSArray *)array {
self.mutableArray = [NSMutableArray arrayWithArray:array];
}
#end
You're adding a private mutableArray property in a class extension and making the public array simply forward to your private mutable one.
With the most recent language extensions of ObjC I tend to remove the
{
NSMutableArray* mutableArray;
}
ivar block entirely, if possible.
And define the ivar thru the synthesization, as such:
#synthesize mutableArray = _mutableArray;
which will generate a NSMutableArray *_mutableArray; instance for you.
Simplest answer: your property type (NSArray) doesn't match your instance variable type (NSMutableArray).
This is yet another good reason that you shouldn't define your own backing variables. Let #synthesize set up your instance variables; don't do it by hand.

How to retain my own objects and properties

I'm not sure I understood how alloc and retain work.
Recently I discovered that the NSString properties were not retained and I had to add [myString copy] when I set them. Which makes me wonder if I misunderstood the whole way of using retain/alloc
Please, may someone tell me if I'm doing it correctly? I read a lot and had a look on open source projects, this let me thing that I may have been wrong since the beginning.
Here is my way of doing it:
/**** VIEW.h *****/
#import "MyClass.h"
#interface MyViewController : UIViewController {
//Is the following line really necessary?
MyClass *myObject;
}
#property (nonatomic, retain) MyClass *myObject;
- (void)defineObject;
#end
.
/**** VIEW.m *****/
#import "VIEW.h"
#implementation MyViewController
#dynamic myObject;
- (void)viewDidLoad
{
[super viewDidLoad];
[self defineObject];
NSLog(#"My object's name is: %#", myObject.name);
}
- (void)defineObject
{
//Here particularly, Why doesn't it work without both alloc and init
//shouldn't "#property (nonatomic, retain) MyClass *myObject;" have done that already?
myObject = [[MyClass alloc] initPersonalised];
[myObject setName:#"my name"];
}
.
/**** MyClass.h *****/
#interface MyClass : NSObject {
//not sure if this line is still necessary
NSString *name;
}
#property (nonatomic, retain) NSString *name;
- (id)initPersonalised;
- (void)setName:(NSString *)name;
- (NSString *)name;
#end
.
/**** MyClass.m *****/
#import "MyClass.h"
#implementation MyClass
#dynamic name;
(id)initPersonalised{
self = [super init];
name = #"Undefined";
}
- (void)setName:(NSString *)name{
self.name = [name copy];
}
- (NSString *)name{
return [self.name copy];
}
#end
I hope you can bring a bit of light, after months of programming this way, I'm less and less sure of doing it well.
This is indeed a topic that every Objective C programmer stumbles upon. There are a few things one needs to know:
Instance variable vs. property access
Within MyViewController,
myObject = xxx;
and
self.myObject = xxx;
are two different things. The first directly assigns to the instance variable and does neither release to old referenced insance nor retain the newly assigned instance. The latter one uses the property setter and thus releases the old and retains the new value.
Deallocation
Even when you have declared an implemented a property that takes care of retaining and releases the values, it won't take care of deallocation when your object (MyViewController in your case) is released. So you must explicitly release it in dealloc:
-(void) dealloc {
[myObject release];
[super dealloc];
}
Now to your code:
The snippet:
myObject = [[MyClass alloc] initPersonalised];
is perfectly okay. When you create an object, you use the pair of alloc and initXXX. The always create an instance with the reference count set to 1. So by directly assigning it to the instance variable, you create a clean constellation. I don't see no other way of creating the instance.
In MyClass you could use #synthesize name instead of #dynamic. Then the compiler would implement name and setName: automatically and you wouldn't need to do it yourself.
Finally, your missing dealloc.
Update:
If you use:
self.myObject = [[MyClass alloc] initPersonalised];
then you have a memory leak because initPesonalised sets the reference count to 1 and the setter of myObject increases it to two. If you want to use the setter, then I has to be:
MyClass* mo = [[MyClass alloc] initPersonalised];
self.myObject = [[MyClass alloc] initPersonalised];
[mo release];
It would be different if you weren't using initXXX to create a new instance. The class NSString for example has many methods called stringXXX, which create a new instance (or return a shared one) that has (conceptually) a reference count of 1 that will later automatically decreased by one. Then you better use the setter:
self.name = [NSString stringWithFormat: #"instance %d", cnt];
If you want to use copy instead of retain for your string property (which is good practice), then you can simply declare your property like this:
#property (nonatomic, copy) NSString *name;
When you then use #synthesize to implement the getter and setter, the compiler will generate them using copy instead of retain.
And NSString *name; is necessary even if you use #property and/or #synthesize to implement the property.
Alloc and init are methods that always go hand-in-hand. alloc allocates space for your object, and init initializes your object to some value. When you call alloc, you are responsible for freeing that object later. If you call copy, you are also responsible for releasing that object later. It's considered good practice to always initialize your objects right after you allocate them.
Now, to answer the questions I found in your code.
#interface MyViewController : UIViewController {
//Is the following line really necessary?
MyClass *myObject;
}
So is that line necessary? That depends. Does it make sense that your object has a MyClass as a property? This is a question only you can answer based on your design. I recommend you to study Object-Oriented Programming in more depth.
- (void)defineObject
{
//Here particularly, Why doesn't it work without both alloc and init
//shouldn't "#property (nonatomic, retain) MyClass *myObject;" have done that already?
myObject = [[MyClass alloc] initPersonalised];
[myObject setName:#"my name"];
}
Not necessarily. You are just providing a pointer to an object of the specified kind. The moment you set your property, depending on the property modifiers, your class will know what to do with MyObject.
In that way, there's no need to call [yourObject copy]. In this way your properties will be copied instead of being retained. Just don't forget to release it later in your -dealloc method, like you would with retain properties.
All in all, this is what I recommend you to study a bit more:
Object-Oriented Programming (not related to your issue, but I can tell you are not comfortable using it. Objective-C is heavily object oriented, so you want to understand OOP).
iOS Memory Management.
You can have a look at the Memory Management Guide. It will help you to better understand the alloc & retain concepts; hope this helps you.

Automatic iVars with #synthesize

I understand that starting with iOS 4, there is now the ability to not declare iVars at all, and allow the compiler to automatically create them for you when you synthesize the property. However, I cannot find any documentation from Apple on this feature.
Also, is there any documentation on best practices or Apple recommended guidelines on using iVars and properties? I have always use properties like this:
.h file
#interface myClass {
NSIndexPath *_indexPath
}
#property(nonatomic, retain) NSIndexPath *indexPath
#end
.m file
#implementation myClass
#synthesize indexPath = _indexPath;
- (void)dealloc {
[_indexPath release];
}
#end
I use the _indexPath instead of indexPath as my iVar name to make sure that I don't ever use indexPath when I need to use self.indexPath. But now that iOS supports automatic properties, I don't need to worry about that. However, if I leave out the iVar declaration, how should I handle releasing it in my dealloc? I was taught to use iVars directly when releasing in dealloc, rather than using the property methods. If I don't have an iVar at design-time, can I just call the property method instead?
I've went through many different ways of dealing with this. My current method is to use the property access in dealloc. The reasons not to are too contrived (in my mind) to not do it, except in cases where I know the property has odd behavior.
#interface Class
#property (nonatomic, retain) id prop;
#end
#implementation Class
#synthesize prop;
- (void)dealloc;
{
self.prop = nil;
//[prop release], prop=nil; works as well, even without doing an explicit iVar
[super dealloc];
}
#end
In constrast, I do the following:
#interface SomeViewController : UIViewController
#property (nonatomic, copy) NSString *someString;
#end
and then
#implementation SomeViewController
#synthesize someString;
- (void)dealloc
{
[someString release], someString = nil;
self.someString = nil; // Needed?
[super dealloc];
}
#end
Note: At some point Apple will enable synthesize-by-default which will no longer require the #synthesize directive.
You can directly access instance variables using -> symbol instead of dot . (which will invoke ivar's corresponding accessor method):
.h
#interface myClass {
}
#property(nonatomic, retain) NSIndexPath *indexPath
#end
.m
#implementation myClass
- (void)dealloc {
[self->indexPath release];
self->indexPath = nil; // optional, if you need it
[super dealloc];
}
#end
Thus you will directly access iVar and not it's corresponding accessor method, obtaining additional benefit - performance.

Managing memory in objective-C for auto properties set as (retain)

If I'm not using garbage collection and I have a auto property set as retain. Should I release the object in my dealloc or does the generated code handle that for me.
More clearly, will the following code leak memory if I don't release name in dealloc.
Person.h
#interface Person : NSObject {
}
#property (retain) NSString* name;
#end
Person.m
#import "Person.h"
#implementation Person
#synthesize name;
#end
The retain/assign/copy attributes of a #property only affects how they would behave in the getter and setter. You do need to manually -release the ivar in -dealloc.
yes this will create memory leak.
You should release it manually or in dealloc to prevent memory leak.
Here is another way to work with this..
//.h file
#interface Person : NSObject
{
NSString* name;
}
#end
//.m file
import "Person.h"
#implementation Person
-(void)ViewdidLoad
{
//You can use this by self.name=[Nsstring StringWithFormat:#""];
}
#end
Thanks
Shyam Parmar