@property and @synthesize
Asked Answered
D

3

9

I'm very new to Objective C. (Two days now). When read about @synthesize, it seemed to overlap with my understanding @property (which I thought I understood) ... So, some details need to be ironed out in my mind ... it's bugging me.

Please correct me if I'm wrong about differences of @property and @synthesize:

If you declare a @property in your @interface, then you're telling the world that users can expect to use standard getters and setters for that property. Futhermore, XCode will make generic getters and setters for you. ... BUT, To what degree does that happen with the @property declaration? ( I.E. does that mean "completely" ... like unseen declarations for it in your @interface, and also unseen code in your @interface?

-Or-

Does @property take care of the unseen code declarations in your @interface only - whereas @synthesize takes care of the unseen code implementation in your @implementation section? )

Depravity answered 4/10, 2012 at 15:4 Comment(2)
Think of it like this if you have a @property more than likely you will need the @synthesize. This is because yes @property is telling the world that a generic getter and setter are needed but the @synthesize is actually creating the getters and setters, you can override this and create your own getters and setters if you like as the ones generated will be very basic. Have a watch of the iTunesU iPad and iPhone Application Development by Paul Hegarty this is the way I think of it and it hasn't failed yet.Realtor
Thanks so much Popeye ... ITunes U is FANTASTIC!!! I'm actually on lesson 4 or Paul's 2011 series. I'm just backing up, reading XCode 4 Learning Objective C along side these series ... still this was not explicitly clear to me.Depravity
S
18

First, note that the latest version of Xcode does not require @synthesize at all anymore. You can (and should) just omit it. That said, here's what the pieces do.

@property is a declaration of accessors. It is just a declaration. There is very little difference between the following:

@property (nonatomic, readwrite, strong) NSString *something;

vs.

- (NSString *)something;
- (void)setSomething:(NSString)aSomething;

The main difference is that declaring these methods using @property lets the compiler automatically generate (synthesize) the implementations for you. There is no requirement that you let the compiler do it for you. You are absolutely free to implement something and setSomething: by hand, and it is common to do. But, if you don't implement them by hand, the compiler will automatically create an ivar for you called _something and create a reasonable implementation for the getter and setter.

In older versions of Xcode, you had to explicitly request the auto-generation using the @synthesize keyword. But that is no longer required. Today, the only reason to use @synthesize is if you want the ivar to have a non-standard name (never do that).

A key point here is that the methods something and setSomething: are just methods. There is nothing magical about them. They're not special "property methods." They're just methods that by convention access a piece of state. That piece of state is often stored in an ivar, but does not need to be.

To be even more clear: object.something does not mean "return the ivar named _something from object." It means "return the result of [object something], whatever that does." It is common for that to return the value of an ivar.

You should declare all of your state (internal and external) using @property declarations, and you should avoid directly declaring ivars. You should also always access your properties via their accessors (self.something), except in the init and dealloc methods. In init and dealloc, you should directly use the ivar (_something).

Scalenus answered 4/10, 2012 at 15:19 Comment(5)
Rob, Thanks so much for your time & response. Watching iOS videos on iTunes U from last year(2011) ... and trying to keep up with changes going on in XCode make for some confusion at times. Listening carefully to the instructor, and even making test with simple code ... heck, even reading XCode documentation didn't fully clear up that @synthesis was not necessary! Helpful confirmation like yours adds to confidence that I didn't learn something wrong ... as I continue along. :-) Now ... if someone has some outside link where I can start thinking properly about MVC - that'd be great!!Depravity
Start here: developer.apple.com/library/ios/#documentation/General/…. Then here: developer.apple.com/library/ios/#featuredarticles/…Scalenus
'You should declare all of your state (internal and external) using @property declarations, and you should avoid directly declaring ivars' are there any times when you should not do this?Insular
The most common case is if you override both the getter and setter, but still need an ivar. You need to declare the ivar then by hand, but it doesn't change access. A rare case I occasionally face is when I have an ivar that is always accessed as a raw memory pointer (a malloc'ed buffer for instance), so there is no use for accessors. See my private ivars in github.com/rnapier/richtext-coretext/blob/master/PinchText/… for an example. But these are rare cases. You should use properties unless there is a compelling reason you cannot.Scalenus
So can I say that the compiler reads the @ property declaration the generate @ synthesize, @ synthesize generates the getter and the setter?Acrefoot
G
7

@property declares a property on your class with whatever atomicity and setter semantics you provide.

With Xcode 4.4, autosynthesis is available wherein you are provided with a backing ivar from your property without declaring it in @synthesize. This ivar has the form of _propertyName where your property name is propertyName.

Glabella answered 4/10, 2012 at 15:12 Comment(2)
This has hit the nail on the head, short sweet and simple. +1Realtor
Yes ... I knew you could "back your property var" with a different ivar ( which should be used by your class, and especially with the getters and setters. ) ... Thanks so very much for your response ... I've overwhelmed with the speed of helpful replies coming in ... (This is my first post here after joining only minutes ago )! - Thanks for taking to time to make this post Alan!Depravity
S
0

Objective-C @property and @synthesize

@property

  • generates get/set method
  • today(from Xcode v4.4 with the LLVM v4.0) @property additionally uses @synthesize inside
    • @synthesize propertyName = _propertyName

@synthesize:

  • generates a new iVar or link with existing iVar
  • generates an implementation of the get/set method with an appropriate iVar

[Case when @synthesize can be used]

@property

@interface SomeClass : NSObject
@property NSString *foo;
@end

//generated code
@interface SomeClass : NSObject
- (NSString *)foo;
- (void)setFoo:(NSString)newFoo;
@end

@synthesize pattern

@synthesize <property_name> = <variable_name>;

//Using
//1. Specify a variable. New variable(variableName) will be generated/linked with existing
@synthesize propertyName = variableName

//if variableName is not exist it generates: 
//NSString *variableName;

//read access
NSString *temp = variableName;

//2. Default. New variable(propertyName - the same name as a property) will be generated/linked with existing
@synthesize propertyName
//is the same as
//@synthesize propertyName = propertyName

//if propertyName is not exist it generates:  
//NSString *propertyName;

//read access
NSString *temp = propertyName;

//if you specify not-existing <property_name>  you  get
//Property implementation must have its declaration in interface '<class_name>' or one of its extensions

previously you had to use next syntax:

@interface SomeClass : NSObject
{
    //1. declare variable
    NSString *_foo;
}
//2. create property
@property NSString *foo;
@end

@implementation SomeClass
//3. link property and iVar
@synthesize foo = _foo;
@end

But today you can use next syntax

@interface SomeClass : NSObject
//1. create property
@property NSString *foo;
@end

Next, the same code, will be generated for both cases

@interface SomeClass : NSObject
{
    //variable
    NSString *_foo; 
}

//getter/setter
- (void)setFoo:(NSString *)newFoo;
- (NSString *)foo;
@end

@implementation SomeClass
- (void)setFoo:(NSString *)newFoo
{
    _foo = newFoo;
}
- (NSString *)foo
{
    return _foo;
}
@end
Sharonsharona answered 16/5, 2021 at 21:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.