When you access an instance variable outside of an object, you should always do so by using properties. What happens when you access an instance variable inside an object?
This is a question that ocer have been hotly debated. It is argued that, in any case, the instance variables should be accessed through attributes, and some say that "access by property" and "direct access" should be used in conjunction. In addition to a few special cases, I strongly recommend that you read the instance variable in the form of direct access, and when setting the instance variable by the property to do.
Consider the following class:
@interface EOCPerson: NSObject
@property (nonatomic, copy) NSString * firstName;
@property (nonatomic, copy) NSString * lastName;
// Quick method to set full name
-(NSString *) fullName;
-(void) setFullName: (NSString *) fullName;
@end
The two "convenient methods", FullName and Setfullname, can be implemented like this:
-(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 foreign names.
* /
-(void) setFullName: (NSString *) fullName
{
NSArray * components = [fullName componentsSeparatedByString: @ ""];
self.firstName = [components objectAtIndex: 0];
self.lastName = [components objectAtIndex: 1];
}
In the Get and set method of FullName, we use "dot syntax" to access related instance variables through storage methods. Assume that you override both methods without accessing the method, but instead directly access the instance variables:
-(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 ways:
-
Because it is not distributed by OC (Method Dispatch), it is of course faster to access instance variables directly. In this case, the code generated by the compiler directly accesses the block of memory for the object instance variable.
-
When you access an instance variable directly, its setting method is not called. This bypasses the memory management definition defined for the related property. For example, direct access to a property declared as copy under ARC does not copy the property, leaving only the new value and releasing the old value.
-
If you access an instance variable directly, it does not trigger a KVO notification, which can cause problems and also depends on the specific object behavior.
-
Access through properties helps to troubleshoot related errors because you can add a breakpoint to the setter, monitor the caller of the property, and access the opportunity.
There is a reasonable way to do this: When the instance variable is written, it is done by its setter, and when the instance variable is read, it is accessed directly. In this way, the ability to increase the speed of the read operation, but also to monitor the write operation of the property. The reason for writing instance variables through setter is that , this ensures that the "memory management definition" of the relevant properties is implemented. However, there are several issues to be aware of when choosing this approach.
The first point to note is how the property value should be set in the initialization method. In this case, the instance variable should always be accessed directly, because the subclass might overwrite (override) the Set method.
In the above example, suppose that Eocperson has a subclass called Eocsmithperson, which represents those who have the surname Smith. The subclass may override the LastName 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 an empty string. If this is done by the setter method, then the child class will be called to set the method, which throws an exception. However, in some cases, you must call the setting method in the initialization method: If the instance variable to be initialized is declared in the parent class, and we cannot access the instance variable directly in the subclass, we need to call the setter.
Another major problem is lazy loading. In this case, the property must be accessed through a getter, otherwise the instance variable will never be initialized. For example, the Eocperson class might use a property to represent the information in the human brain, and the object it refers to is quite complex. Because this property is not commonly used, and the creation cost is higher, so we will lazy load it in the getter.
-(EOCBrain*)brain
{ if(!_brain)
{
_barin = [Brain new];
} return brain;
}
In this case, if you do not use the Getter method and directly access the instance variable, you will see that there is no initialized brain, so if lazy loading is used, the brain property must be accessed through getter.
Induction:
-
When reading data inside an object, it should be read through an instance variable, while writing the data should be written by property.
-
In initialization and Dealloc methods, you should always read and write data through instance variables.
-
Sometimes the lazy-loading technique is used to configure some data, in which case the data needs to be read through attributes.
Try to access instance variables directly inside the object--effictive objective-c transcription