How can I declare @property but prevent ivar from creating it?

I have a class A that provides a way to get and set an object of type Foo . In a property language, I usually declare this in an interface:

 @property (nonatomic, strong) Foo * foo; 

This (in modern ObjC) generates both accessors and ivar, _foo for storage.

If I want to do user work in accessors, I can implement one or both of them myself. But what if I not only want to do individual work, I really do not want Ivar? In other words, I am doing something else with the Foo object, for example, passing it back and forth to another internal object with which I am a member. I really don't need to store the repository for Foo in instance A at all.

I seem to have two options:

  • Declare a property, implement both accesses, and simply ignore the fact that the compiler creates storage for _foo and never uses it.
  • I explicitly declare my helpers: - (Foo *)foo and - (void)setFoo:(Foo *)foo in the interface, as I used in the up-to-date ObjC.

The former seems inelegant at runtime, and the latter seems inelegant in the declaration (where I probably now have a combination of properties and properties similar to accessories).

Is there a way to declare a property and use it as a pure declaration?

+7
objective-c cocoa
source share
3 answers

If you override both setter and getter and do not use the variable in the setter and getter, the variable will not be created.

For example, if you have a class for which you want the firstName and lastName property, but maybe also setter and getter for the fullName property, if your fullName installer just parses the string in firstName and lastName and sets these properties for this (and never saves the full string to the fullName variable), and your fullName getter just returns concatenated firstName + lastName and never uses the fullName variable, it will never be created.

This is according to Apple's official documentation. Scroll down to "You can implement user access methods"

+4
source share

Use the @dynamic keyword in the implementation file. The usual discussion of @dynamic describes it as not creating accessors at compile time. It is usually not mentioned that it also has nothing to do with creating a repository for this property, which in this case is desirable.

 @implementation A @dynamic foo; - (Foo *)foo { // get a Foo from somewhere and return it. } - (void)setFoo:(Foo *)foo { // do something with foo } @end 

(Note: answered my own question, since I discovered this when writing the question, and it seemed interesting and not obvious.)

+9
source share

@dynamic is probably the way to go.

However, there are two more ways to do this:

  • Not implemented category

    You can use an unrealized category to declare a property, but not get a backup storage:

     @interface Foo : NSObject @end @interface Foo (UnimplementedProperties) @property (strong) id bar; @end @implementation Foo @end 

    Without declaring a category implementation ( @implementation Foo (UnimplementedProperties) ), the properties will not be synthesized.

  • Protocol

    You can declare properties in a protocol and then make your class conform to that protocol. This has the same effect as the unrealized category: methods are declared, but properties are not synthesized.

     @protocol FooProperties <NSObject> @property (strong) id bar; @end @interface Foo : NSObject <FooProperties> @end 
+2
source share

All Articles