Alternative Use of Properties?

Tue, Aug 12

While scanning a few code examples inside the iPhone SDK, I bumped into something interesting. I wrote a short example to mimic what I found…take a look at the following interface declaration:

1
2
3
4
5
6
7
8
9
@interface SomeClass : NSObject
{
  NSString *str;
  NSDate *date;
} 
 
@property (nonatomic, retain) NSString *str;
@property (nonatomic, retain) NSDate *date;
@property (readonly) NSString *testSomething;

The only aspect that should standout is the property declaration for testSomething . Notice there is no instance instance variable tied to this declaration. This is different if for no reason other than the typical use for properties is as a shorthand for declaring accessor methods for instance variables.

So what happens if we now add an instance method, such as shown below, inside the implementation file for SomeClass (and don’t include either a @synthesize or @dynamic declaration)?

1
2
3
4
- (NSString *) testSomething
{
  return @"Foo";
}

Well, for one thing, we can now access the testSomething method using dot syntax.

1
2
3
SomeClass *ptr = [[SomeClass alloc] initWithStrAndDate:@"Fubar"];
...
NSLog(@"test: %@", ptr.testSomething);

This is intriguing. I couldn’t find any specific references to using properties in this manner. Is this simply a side-effect of how properties are implemented?

If you can shed any light on this, including whether this is a common/good practice, please post a comment.

7 comments

The redundancy in property declarations drives me nuts (as does some of the other unnecessary verbosity in Obj-C and Apple’s APIs).

I spotted this the other day in Apple’s Objective C Guide, under “Using properties”; so I guess at some time in the future we won’t have to put up with it:

There are differences in the behavior that depend on the runtime (see also “Runtime Differences”):
* For the legacy runtimes, instance variables must already be declared in the @interface block. If an instance variable of the same name and compatible type as the property exists, it is used—otherwise, you get a compiler error.
* For the modern runtimes, instance variables are synthesized as needed. If an instance variable of the same name already exists, it is used

by Adrian on Aug 13, 2008. #

Hey John, I remember from reading about properties the other day that the default value for a property directives is @dynamic. So, if you declare a property in your interface, but do not specify @synthesize in your implementation it will default to dynamic and expect you to implement a getter/setter corresponding to the @property you’ve defined in the implementation or at runtime.

by Paul C on Aug 14, 2008. #

I think it is because properties do not need to be directly tied to individual ivars.

How about this as an example

@interface SomeClass : NSObject
{
NSString *firstName
NSString *lastName
}
@property (copy, readwrite) NSString *firstName;
@property (copy, readwrite) NSString *lastName;
@property (readonly) NSString *fullName;

@end

Now, in the implementation, you explicitly define the getter which operates on the other properties.

- (NSString *)fullName
{
NSString *retString;
retString = [NSString stringWithFormat:(@"%@ %@", firstName, lastName)];
}

You could have used self.firstName and self.lastName above.

by stompy on Aug 14, 2008. #

It’s entirely standard, use it. You can also override the property setter in the same way

-(void) setSomeProperty:(id) someValue{
[someValue retain];
[someProperty release];
someProperty = someValue;
}

Where you have a someProperty property.. of course you can put in whatever you want.

by bugfaceuk on Aug 14, 2008. #

Is it just me, or does this resemble how Ruby handles accessors?

by Apocryphon on Jul 12, 2011. #

@Paul C: “the default value for a property directives is @dynamic” No, that is wrong. If you use @dynamic, it will not expect you to provide an implementation in @implementation. If you want to provide getters/setters yourself, you should use no implementation directive, and the compiler will check and warn you if they’re missing.

by bob on Jul 20, 2011. #

“Notice there is no instance instance variable tied to this declaration.”
An instance variable is only relevant if you use @synthesize (and in newer Objective-C runtime, you can omit it and it will generate an instance variable for you). Since you’re not using @synthesize, it doesn’t matter.

“So what happens if we now add an instance method, such as shown below, inside the implementation file for SomeClass (and don’t include either a @synthesize or @dynamic declaration)?”
That’s the whole point of a property — it doesn’t necessarily have to be backed by just an instance variable (if that were the case we would just use public instance variables), it can be backed by custom code, but it will appear the same to the outside (abstraction).

What is even more intriguing, is that it appears sometimes possible to access a method *not declared as a property* using the dot syntax. Try the following: remove the @property declaration, add a method declaration for -(NSString *)testSomething in your @interface, and try using the dot syntax. THIS is a really weird way to use the property syntax.

by bob on Jul 20, 2011. #