EmptyStack
EmptyStack

Reputation: 51374

What is the best way to declare a property?

We declare properties using the @property keyword and synthesize it in the implementation file. My question is,

What if I declare a property using the @property keyword and also declare a variable in the interface block with the same name? For example, consider the following code,

Interface:

@interface myClass : NSObject {

    NSString *myClass_name;  // LINE 1
}

@property(nonatomic, retain) NSString *myClass_name;  // LINE 2

@end

Implementation:

@implementation myClass

@synthesize myClass_name  // LINE 3

@end

Declaring myClass_name in LINE 1 will make any problem? Like any reference problem or any unnecessary memory consumption problem?

Upvotes: 1

Views: 490

Answers (4)

Míng
Míng

Reputation: 2608

The following is the Object-oriented way:

DeclaringProperties.h

@interface DeclaringProperties : NSObject
// ivars and {} can be omitted

@property (nonatomic, readwrite, retain) NSString *normal;
@property (nonatomic, readwrite, retain) NSString *alias;
@property (nonatomic, readonly, retain) NSString *readonly;

- (id) initWithNormal:(NSString *)aNormal alias:(NSString *)alias;

@end

DeclaringProperties.m

#import "DeclaringProperties.h"

// private interface
@interface DeclaringProperties ()

@property (nonatomic, readwrite, retain) NSString *readonly; // readwrite for self
@property (nonatomic, readwrite, retain) NSString *private;
@property (nonatomic, readwrite, retain) NSString *retain;

@end

#pragma mark -

@implementation DeclaringProperties

@synthesize normal, alias = _alias, readonly, private, retain;

// You can not use "normal" here;
// But you can still use "alias", and it is highlighted in XCode!
- (id) initWithNormal:(NSString *)aNormal alias:(NSString *)alias {
    self = [super init];
    if (self) {
        self.normal = aNormal;
        self.alias = alias;
        self.readonly = @"readonly";
        self.private = @"private";

        // allocated(copied) variable for retained(copied) property should be released or autoreleased
        NSString *alloc = [[NSString alloc] init];
        self.retain = alloc;
        [alloc release];
        // or
        self.retain = [[NSString alloc] init];
        [self.retain release];
        // or
        self.retain = [[[NSString alloc] init] autorelease];
        // I don't like ;)
        retain = [[NSString alloc] init];
    }
    return self;
}

- (void) dealloc {
    self.normal = nil;
    self.alias = nil;
    self.readonly = nil;
    self.private = nil;
    self.retain = nil;
    [super dealloc];
}

@end

Upvotes: 1

EmptyStack
EmptyStack

Reputation: 51374

I got the following content from Apple's doc for Declared Properties. I am posting it here, so that it may be helpful for someone in future.

Runtime Difference

In general the behavior of properties is identical on all runtimes (see Runtime Versions and Platforms in Objective-C Runtime Programming Guide). There is one key difference: the modern runtime supports instance variable synthesis whereas the legacy runtime does not.

For @synthesize to work in the legacy runtime, you must either provide an instance variable with the same name and compatible type of the property or specify another existing instance variable in the @synthesize statement. With the modern runtime, if you do not provide an instance variable, the compiler adds one for you. For example, given the following class declaration and implementation:

@interface MyClass : NSObject {

    float sameName;
    float otherName;
}

@property float sameName;
@property float differentName;
@property float noDeclaredIvar;

@end


@implementation MyClass

@synthesize sameName;
@synthesize differentName=otherName;
@synthesize noDeclaredIvar;

@end

the compiler for the legacy runtime would generate an error at @synthesize noDeclaredIvar; whereas the compiler for the modern runtime would add an instance variable to represent noDeclaredIvar.

Upvotes: 1

Matt
Matt

Reputation: 678

No, in fact, declaring properties like that expects it. You could replace your declaration to:

@interface MyClass : NSObject {
    NSString *ivar;
}

@property (nonatomic, retain) NSString *myClass_name;

@end

And then change your implementation to

@implementation MyClass

@synthesize myClass_name = ivar;

@end

(If you don't specify the = some_ivar, it will assume the ivar has the same name as the property.)

You always need to have the following lines:

  • Declaration of the property (Line 2)
  • Synthesization of the property (Line 3)

When you synthesize the property, if you do not specify which ivar to use (by using =ivar at the end), it will assume that there is an ivar with the same name as the property.

Upvotes: 3

Snehal
Snehal

Reputation: 597

Declaring properties and synthesizing it will not create any reference problem in your case. Doing this will create accessor and setter methods for your instance variable in your class. If the variable names in the property and the one declared in the class, then the xcode will refer both as a single variable.

Line 3 and Line 4 are must. Line 1 is optiona

Upvotes: 1

Related Questions