When should I use @synthesize explicitly?

As far as I know, since Xcode 4.4, @synthesize will automatically generate property access objects. But now I read the sample code about NSUndoManager , and in the code he noticed that @synthesize explicitly added. How:

 @interface RootViewController () @property (nonatomic, strong) NSDateFormatter *dateFormatter; @property (nonatomic, strong) NSUndoManager *undoManager; @end @implementation RootViewController //Must explicitly synthesize this @synthesize undoManager; 

Now I feel puzzled ... When should I explicitly add @synthesize to my code?

+49
properties objective-c synthesize
Nov 05 '13 at 8:19
source share
7 answers

There are many answers, but also a lot of confusion. I will try to make some kind of order (or increase the clutter, let's see ...)

  • Stop talking about Xcode. Xcode is an IDE . clang - compiler . This feature we are discussing is called property auto-synthesis, and it is the Objective-C extension supported by clang , which is the default compiler used by Xcode.
    Just to be clear, if you switch to gcc in Xcode, you will not be able to use this function (regardless of the version of Xcode). Similarly, if you use a text editor and compile using clang from the command line, you will.

  • Thanks to autosynthesis, you do not need to explicitly synthesize a property, since it will be automatically synthesized by the compiler as

     @synthesize propertyName = _propertyName 

    However, there are a few exceptions:

    • readwrite property with custom getter and setter

      if both selective implementations of getter and setter are provided, the property will not be automatically synthesized

    • readonly property with custom getter

      when providing a custom getter implementation for the readonly property, this will not be automatically synthesized

    • @dynamic

      when using @dynamic propertyName property will not be automatically synthesized (quite obvious, since @dynamic and @synthesize are mutually exclusive)

    • properties declared in @protocol

      when compliant with the protocol, any property defined by the protocol will not be automatically synthesized

    • properties declared in the category

      this is a case where the @synthesize directive @synthesize not be automatically inserted by the compiler, but these properties also cannot be synthesized manually. Although categories can declare properties, they cannot be synthesized at all, since categories cannot create ivars. For the sake of completeness, I add that it is still possible to fake property synthesis using Objective-C runtime .

    • redefined properties (new since clang-600.0.51, shipping with Xcode 6, thanks Marc Schlüpmann)

      when you redefine a property of a superclass, you must explicitly synthesize it

It is worth noting that synthesizing a property automatically synthesizes ivar support, so if there is no synthesis of properties, ivar will also be absent unless explicitly declared.

Except in the last three cases, the general philosophy is that whenever you manually specify all the information about a property (by implementing all access methods or using @dynamic ), the compiler assumes that you want to completely control the property and it will turn off auto-synthesis on it .

Apart from the cases listed above, the only use of explicit @synthesize would be to specify a different ivar name. However, conventions are important, so my advice is to always use the default names.

+115
Nov 06 '13 at
source share

Unless you explicitly use @synthesize , the compiler will understand your property in the same way if you wrote

 @synthesize undoManager=_undoManager; 

then you can write things like:

 [_undoManager doSomething]; // iVar [self.undoManager doSomethingElse]; // Use generated getter 

This is a common agreement.

if you write

 @synthesize undoManager; 

you will have:

 [undoManager doSomething]; // iVar [self.undoManager doSomethingElse]; // Use generated getter 

Personally, I stop using @synthesize , as it is optional. For me, the only reason to use @synthesize is to bind iVar to @property . If you want to generate a specific getter and setter for it. But there is no iVar in this code iVar , I think this @synthesize useless. But now I think the new question is: “When to use iVar ?”, And I have no other answer than “never” for this!

+15
Nov 05 '13 at 8:33
source share

When should I explicitly add @synthesize to my code?

As a rule, if it is necessary: ​​you will probably never encounter a situation when it is necessary.

In one case, you may find it useful.

Suppose you write both a custom getter and a setter, but you want the instance variable to return it. (For an atom’s property, this is as simple as the desire for a custom setter: the compiler will write a getter if you specify an installer for a monatomic property, but not an atomic property.)

Consider this:

 @interface MyObject:NSObject @property (copy) NSString *title; @end @implementation MyObject - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end 

This will not work because _title does not exist. You specified both getter and setter, so Xcode (correctly) does not create a database instance variable for it.

enter image description here

You have two options for its existence. You can either change @implementation to this:

 @implementation MyObject { NSString *_title; } - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end 

Or change it to this:

 @implementation MyObject @synthesize title = _title; - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end 

In other words, although synthesis is never needed * for practical purposes, it can be used to define property instance variables when you provide getter / setter. You can decide which form you want to use.

In the past, I preferred to specify an instance variable in @implementation {} , but now I think that the @synthesize route is the best choice, as it removes the redundant type and explicitly binds the substitution variable to the property:

  • Change the type of the property and change the type of the instance variable.
  • Change your storage classifier (for example, make it weak rather than strong or strong rather than weak) and the storage definition will change.
  • Delete or rename the property, and @synthesize will generate a compiler error. You will not end up with instance instances of variables.

* - I know one case when it was necessary, relating to the division of functions into categories in several files. And I won’t be surprised if Apple fixes it or even already has it.

+9
Nov 05 '13 at 17:42
source share

OK, when you create the property ...

 @property NSString *name; 

Xcode automatically synthesizes iVar as if you wrote ...

 @synthesize name = _name; 

This means that you can access the property with ...

 self.name; // or _name; 

It will work, but only self.name really uses access methods.

There is only one time when auto synthesis does not work.

If you rewrite but the installer AND getter method, you will need to synthesize iVar.

You are fine if you just redefine the setter or just redefine the recipient. But if you do this, the compiler will not understand this, and you will need to synthesize it manually.

Generally though.

Do not do iVars. Just use the property. Do not synthesize it.

+3
Nov 05 '13 at 17:47
source share

Synthesis of properties is required when a property is declared in the protocol. It will not be automatically synthesized in the implementation interface.

+1
Nov 06 '13 at
source share

Thanks for the clarification. I had a similar problem.

 @synthesize firstAsset, secondAsset, audioAsset; @synthesize activityView; 

So, now, having commented on them, I went through and replaced each event, for example

self.firstAsset It seems that I could also use firstAsset, but it seems to me that I see too much too.

0
May 6 '14 at 15:41
source share

Xcode does not require an explicit @synthesize .

If you don't write @synthesize , this is the same as doing:

 @synthesize manager = _manager; 

Sample code might be old. They will be updated soon.

You can access your properties, for example:

 [self.manager function]; 

This is an Apple Recommended Agreement. I follow him and I recommend you too!

-one
Nov 05 '13 at 8:38
source share



All Articles