Reason to use ivars vs properties in objective c

前端 未结 5 1414
说谎
说谎 2020-11-27 05:50

I have been unable to find any information on this topic and most of what I know about it has come by complete accident (and a few hours of trying to figure out why my code

相关标签:
5条回答
  • 2020-11-27 06:06

    I typically just use @property and @synthenize.

    @property gives the compiler and the user directions on how to use your property. weather it has a setter, what that setter is. What type of value it expects and returns. These instructions are then used by the autocomplete (and ultimately the code that will compile against the class) and by the @synthesize

    @synthesize will by default create an instance variable with the same name as your property (this can get confusing)

    I typically do the following

    @synthesize propertyItem = _propertyItem; 
    

    this will by default create a getter and a setter and handle the autorelease as well as create the instance variable. The instance variable it uses is _propertyItem. if you want to access the instance variable you can use it as such.

    _propertyItem = @"Blah";
    

    this is a mistake tho. You should always use the getter and setter. this will let the app release and renew as needed.

    self.propertyItem = @"Blah";
    

    This is the better way to handle it. And the reason for using the = _propertyItem section of synthesize is so you cannot do the following.

    propertyItem = @"Blah"; // this will not work.
    

    it will recommend you replace it with _propertyItem. but you should use self.propertyItem instead.

    I hope that information helps.

    0 讨论(0)
  • 2020-11-27 06:14

    You can think of the syntax for synthesizing properties as @synthesize propertyName = variableName.

    This means that if you write @synthesize highscore = _highscore; a new ivar with the name _highscore will be created for you. So if you wanted to you could access the variable that the property is stored in directly by going to the _highscore variable.

    Some background

    Prior to some version of the compiler that I don't remember the synthesis statement didn't create the ivar. Instead it only said what variable it should use so you had to declare both the variable and the property. If you synthesized with a underscore prefix then your variable needed to have the same prefix. Now you don't have to create the variable yourself anymore, instead a variable with the variableName that you specified in the synthesis statement will be created (if you didn't already declare it yourself in which case it is just used as the backing variable of the property).

    What your code is doing

    You are explicitly creating one ivar called highscore when declaring the variable and then implicitly creating another ivar called _highscore when synthesizing the property. These are not the same variable so changing one of them changes nothing about the other.

    Should you use variables or not?

    This is really a question about preference.

    Pro variables

    Some people feel that the code becomes cleaner if you don't have to write self. all over the place. People also say that it is faster since it doesn't require a method call (though it is probably never ever going to have a measurable effect on your apps performance).

    Pro properties

    Changing the value of the property will call all the necessary KVO methods so that other classes can get notified when the value changes. By default access to properties is also atomic (cannot be accessed from more then one thread) so the property is safer to read and write to from multiple thread (this doesn't mean that the object that the property points to is thread safe, if it's an mutable array then multiple thread can still break things really bad, it will only prevent two threads from setting the property to different things).

    0 讨论(0)
  • 2020-11-27 06:16

    This may be an old question.. but in "modern times", @synthesize- is NOT necessary.

    @interface       SomeClass : NSObject
    @property NSString * autoIvar;
    @end
    @implementation  SomeClass
    - (id) init { return self = super.init ? _autoIvar = @"YAY!", self : nil; }
    @end
    

    The _underscored backing ivar IS synthesized automatically... and is available within THIS class' implementation, directly (ie. without calling self / calling the automatically generated accessors).

    You only need to synthesize it if you want to support subclass' ability to access the _backingIvar (without calling self), or for myriad other reasons, described elsewhere.

    0 讨论(0)
  • 2020-11-27 06:21

    In your example, @synthesize timesPlayed = _timesPlayed; creates a new ivar called _timesPlayed and the property refers to that ivar. timesPlayed will be an entirely separate variable with no relation whatsoever to the property. If you just use @synthesize timesPlayed; then the property will refer to timesPlayed.

    The purpose of the underscore convention is to make it easier to avoid accidentally assigning directly to an ivar when you want to be doing it through the property (i.e. through the synthesized setter method). However, you can still acces _timesPlayed directly if you really want to. Synthesizing a property simply auto-generates a getter and setter for the ivar.

    In general you do not need to declare an ivar for a property, although there may be special cases where you would want to.

    0 讨论(0)
  • 2020-11-27 06:22

    You can just use @property and @synthesize without declaring the ivars, as you suggested. The problem above is that your @synthesize mapped the property name to a new ivar that is generated by the compiler. So, for all intents and purposes, your class definition is now:

    @interface Test : NSObject {
    int timesPlayed;
    int highscore;
    int _timesPlayed;
    int _highscore;
    }
    ...
    @end
    

    Assigning a value directly to the ivar timesPlayed will never show up if you access it via self.timesPlayed since you didn't modify the correct ivar.

    You have several choices:

    1 Remove the two ivars you declared in your original post and just let the @property / @synthesize dynamic duo do their thing.

    2 Change your two ivars to be prefixed by an underscore '_'

    3 Change your @synthesize statements to be:

    @implemenation Test
    @synthesize timesPlayed;
    @synthesize highscore;
    
    ...
    
    0 讨论(0)
提交回复
热议问题