Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modern Objective-C (2013) and declaring ivars/using @property, @dynamic, and @synthesize

With the current version of Objective-C, what are the official standards and best practices for declaring ivars, using @property and @synthesize? There are a lot of posts and resources on the topic but most of them are fairly antiquated from a year or two ago. I recently learned to only declare ivars in a statement block in the implementation of a class so that the encapsulation principles of OOP aren't broken but is declaring ivars even necessary in this day and age? What would be a possible use case where doing:

@interface MyClass()
@property (nonatomic) NSString* data;
@end

@implementation MyClass{
    @private
        NSString* _data;
}
@end

is necessary? To further that, is it ever necessary to use @synthesize? My understanding is that using @property will auto-synthesize both the accessor methods as well as the backing ivars. I've done some experimentation and I noticed that when I don't declare NSString* _data', I can still access_data' in my class implementation. Does that mean that declaring ivars come down to a matter of style, up to the discretion of the programmer? Could I condense my code and remove all ivar declarations in the statement blocks in my implementation and just use @property in my private interface? If that's not the case, what are the advantages and disadvantages of explicitly declaring ivars?

Finally, @dynamic. From what I can gather, it's used to say to the compiler, "Hey compiler, don't auto-generate the accessor method and don't worry if you don't find an implementation for it, I'll provide one at runtime". Is that all @dynamic is used for or is there more to it?

I just want to clarify all these things because it seems like there's a lot of different opinions and that there's not necessarily one right answer. Plus as Objective-C grows and progresses, those answers will change so it'll be nice to have a concise and up-to-date guide. Thanks everyone! (Also if there's anything that I could word better or make clearer, let me know)

EDIT:

In summary, what I'm asking is this:

1) Is declaring ivars with modern Objective-C necessary? 2) Can I achieve the same effects of declaring ivars and corresponding properties by just using @property? 3) What is @dynamic used for? 4) Can I completely forgo the use of @synthesize or is there a good use case for it?

Upvote and down vote as you see fit.

like image 367
barndog Avatar asked Nov 22 '25 11:11

barndog


1 Answers

There's a lot to answer here. I'll break it down:

Declaring ivars

As you've correctly noted, modern versions of the compiler will synthesize backing instance variables for declared @properties. The exception to this is on 32-bit Macs, where the modern Objective-C runtime, including non-fragile instance variables, is not available. Assuming your application is not targeting 32-bit OS X, you don't need to explicitly declare the backing ivar for an @property.

If you still want to use an ivar directly, without a corresponding @property (something I consider a bad idea most of the time), you of course must still explicitly declare the ivar.

@dynamic

@dynamic is as you've said meant to tell the compiler "don't synthesize accessors for this property, I'll do it myself at runtime". It's not used all that often. One place it is used is in NSManagedObject subclasses, where if you declare a modeled property in the header, you don't want to compiler to complain that there's no implementation of accessors for that property, nor do you want it to generate accessors itself. NSManagedObject generates accessors for modeled properties at runtime. The story is similar for custom CALayer subclasses.

@synthesize

@synthesize explicitly tells the compiler to synthesize accessor methods, and (on iOS and 64-bit Mac) a corresponding ivar for the specified property. There are three main cases where you still need to use it:

  1. 32-bit Mac apps.
  2. If you've written your own custom setter and getter (or just getter for readonly properties). In this case, the compiler won't synthesize accessors because it sees yours. However, it also won't synthesize the backing ivar. So, you must use @synthesize someProperty = _someProperty;, to tell the compiler to synthesize an ivar. It still won't synthesize accessor methods of course. Alternatively, you can explicitly declare a backing ivar. I favor using @synthesize in this case.
  3. If you want to use a different name for the property's backing ivar than the default (property name with an added underscore prefix). This is rare. The main case I can think of for using it is when transitioning existing, older code, that includes direct ivar access and where the ivars are not underscore-prefixed.
like image 58
Andrew Madsen Avatar answered Nov 24 '25 01:11

Andrew Madsen