Try to directly access instance variables within the object, and the object instance variables
When accessing instance variables outside the object, we should always use the attributes. What should we do when accessing instance variables inside the object?
This is a hot topic that OCer has been discussing. some people think that the instance variables should be accessed through attributes in whatever circumstances; others also say that "access through attributes" and "direct access" should be used together. in addition to some special cases, I strongly recommend that you use direct access when reading instance variables, and use attributes when setting instance variables.
See the following classes:
@ Interface EOCPerson: NSObject @ property (nonatomic, copy) NSString * firstName; @ property (nonatomic, copy) NSString * lastName; // shortcut for setting the full name-(NSString *) fullName;-(void) setFullName :( NSString *) fullName; @ end
FullName and setFullName can be implemented as follows:
-(NSString *) fullName {return [NSString stringWithFormat: @ "% @", self. firstName, self. lastName];}/*** the following method assumes that all full names have only two parts. Of course, this method can also be rewritten to support external names */-(void) setFullName :( NSString *) fullName {NSArray * components = [fullName componentsSeparatedByString: @ ""]; self. firstName = [components objectAtIndex: 0]; self. lastName = [components objectAtIndex: 1];}
In the methods for obtaining and setting fullName, we use the dot syntax to access related instance variables through the storage method. assume that the two methods are rewritten to directly access the instance variables instead of the access method:
-(NSString*)fullName{ return [NSString stringWithFormat:@"%@ %@",_firstName,_lastName];}-(void)setFullName:(NSString *)fullName{ NSArray *components = [fullName componentsSeparatedByString:@" "]; _firstName = [components objectAtIndex:0]; _lastName = [components objectAtIndex:1];}
There are several differences between the two methods:
Because method dispatch is not distributed through the OC method, direct access to instance variables is certainly faster. in this case, the code generated by the compiler directly accesses the memory of the object instance variable.
When you access instance variables directly, the setting method is not called. this bypasses the "Memory Management definition" defined for related properties ". for example, if you directly access an attribute declared as copy under ARC, the attribute will not be copied, but the new value will be retained and the old value will be released.
If you directly access the instance variables, KVO notifications are not triggered. Whether the problem occurs depends on the specific object behavior.
Attribute-based access helps you troubleshoot related errors, because you can add breakpoints to setter to monitor the caller and access time of this attribute.
There is a reasonable solution, that is, when writing instance variables, it is done through its setter, And when reading instance variables, it is directly accessed. in this way, you can increase the read speed and monitor write operations on attributes. the primary reason for writing instance variables through setter is that the "Memory Management definition" of relevant attributes can be implemented. however, when using this method, you need to pay attention to several issues.
The first thing to note is how to set the attribute value in the initialization method. In this case, you should always directly access the instance variable, because the subclass may overwrite the override setting method.
In the preceding example, assume that EOCPerson has a subclass called EOCSmithPerson, which indicates the Smith-surnamed person. This subclass may override lastName corresponding to the setting method:
-(void)setLastName:(NSString *)lastName{ if (![lastName isEqualToString:@"Smith"]) { [NSException raise:NSInvalidArgumentException format:@"Last name must be Smith "]; } self.lastName = lastName;}
In the default Initialization Method of the parent class EOCPerson, the last name may be set to a null string. in this case, if the setter method is used, the subclass setting method is called to throw an exception. however, in some cases, you must call this setting method in the initialization method: If the instance variable to be initialized is declared in the parent class, if we cannot directly access the instance variable in the subclass, we need to call setter.
Another major problem is: lazy loading. in this case, the attributes must be accessed through getter, otherwise the instance variables will never be initialized. for example, the EOCPerson class may use an attribute to represent information in the human brain. The object represented by this attribute is quite complex. because this attribute is not commonly used and the Creation cost is high, we will perform lazy loading on it in getter.
-(EOCBrain*)brain{ if(!_brain) { _barin = [Brain new]; } return brain;}
In this case, if the getter method is not used and the instance variables are directly accessed, the uninitialized brain will be displayed. Therefore, if lazy loading is used, you must use getter to access the brain attribute.
Summary:
When reading data inside an object, it should be read through instance variables. If data is written, it should be written through attributes.
In initialization and dealloc methods, data should always be read and written through instance variables.
Sometimes the lazy loading technology is used to configure certain data. In this case, data needs to be read through attributes.