Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Objective‑C Properties: @property, @synthesize, and @dynamic

Tech 1

Objective‑C Properties: @property, @synthesize, and @dynamic

@property

Declaring a property instructs the compiler to generate an accessor pair and a backing instance variable (ivar) when needed.

Example:

@interface MyViewController : UIViewController
@property (nonatomic, assign, getter=isReady) BOOL ready;
@end

The above can be expanded (conceptually) into an ivar plus explicit setter/getter:

@interface MyViewController : UIViewController {
    BOOL _ready;
}
- (void)setReady:(BOOL)value;
- (BOOL)isReady;
@end

@implementation MyViewController
- (void)setReady:(BOOL)value {
    _ready = value;
}
- (BOOL)isReady {
    return _ready;
}
@end

When you omit explicit accessor implementations, modern compielrs auto‑synthesize them. By default, the auto‑synthesized ivar is named with a leading underscore: _propertyName.

@synthesize

@synthesize controls how accessors are generated and which ivar they use.

  1. Default mapping

When you write @synthesize without specifying a backing ivar, the compiler creates an ivar that matches the property name exactly (no underscore) and wires accessors to it.

@interface StatusController : NSObject
@property (nonatomic, assign) BOOL active;
@end

@implementation StatusController
@synthesize active; // generates ivar named `active`
@end

Equivalent manual form:

@interface StatusController : NSObject {
    BOOL active;
}
- (void)setActive:(BOOL)flag;
- (BOOL)active;
@end

@implementation StatusController
- (void)setActive:(BOOL)flag { active = flag; }
- (BOOL)active { return active; }
@end

Important: With @synthesize active; the ivar is active (no underscore). This differs from auto‑synthesis when @synthesize is omitted, where the compiler creates _active by default.

  1. Custom ivar mapping

You can explicitly bind a property to any ivar you choose.

@interface Metrics : NSObject {
    BOOL backingFlag;
}
@property (nonatomic, assign) BOOL enabled;
@end

@implementation Metrics
@synthesize enabled = backingFlag;
@end

Equivalent manual form:

@interface Metrics : NSObject {
    BOOL backingFlag;
}
- (void)setEnabled:(BOOL)v;
- (BOOL)enabled;
@end

@implementation Metrics
- (void)setEnabled:(BOOL)v { backingFlag = v; }
- (BOOL)enabled { return backingFlag; }
@end

The common underscore pattern is also supported:

@interface Store : NSObject
@property (nonatomic, assign) BOOL loaded;
@end

@implementation Store
@synthesize loaded = _loaded; // accessors read/write `_loaded`
@end

Auto‑synthesis and naming

  • If you declare a property and do not provide accessors or an @synthesize/@dynamic, the compiler auto‑synthesizes accessors and an ivar named _propertyName.
  • If you write @synthesize propertyName; explicitly, the ivar becomes propertyName (no underscore) unless you map it: @synthesize propertyName = someIvar;

Legacy behavior

Before Xcode 4.4 (clang 3.1/LLVM 4.0 era), you typically wrote both an ivar and @synthesize property = _property; explicitly. Auto‑synthesis was introduced later, making that pattern the default unless overridden.

A subtle pitfal

Mixing an explicit @synthesize with a separately declared underscore ivar often leads to logic errors.

@interface Player : NSObject {
    BOOL _muted;      // declared but not used by accessors below
}
@property (nonatomic, assign, getter=isMuted) BOOL muted;
@end

@implementation Player
@synthesize muted; // creates ivar `muted` (no underscore)

- (void)startPlayback {
    self.muted = YES; // writes to `muted`
    if (_muted) {     // checks `_muted`, which is still NO
        [self applySilentMode];
    }
}

- (void)applySilentMode { /* ... */ }
@end

Here, _muted and muted are different ivars. Avoid declaring a parallel underscore ivar when using @synthesize property; or map explicitly: @synthesize muted = _muted;.

@dynamic

@dynamic tells the compiler that accessor methods will be supplied at runtime and should not be auto‑synthesized. It asserts "don’t generate ivars or accessors; they’ll appear dynamically."

Typical with Core Data:

@interface Person : NSManagedObject
@property (nullable, nonatomic, copy) NSString *name;
@end

@implementation Person
@dynamic name; // NSManagedObject provides accessors via the runtime
@end

Advanced uses include adding accessor implementations at runtime (e.g., via class_addMethod) or handling them through message forwarding. In ordinary app code, @dynamic is uncommon compared to auto‑synthesized properties.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.