So, for a little behind the scenes action. The previous post about Header Files was originally going to be about classes. But then after I started writing, I realized if I continued on to talking about classes, the post was going to be longer than I would want to read, so I decided to just split off the header file topic entirely, and save more discussion of classes for later. That’s why I wrote about such an esoteric topic as “Header Files”. I also like the word esoteric, so expect that to show up in this blog every so often.
Anyway, back to what I originally was going to write about, classes. Classes are probably the most important thing in object oriented programming. They are the very constructs that objects are created from. For a physical analogy, lets say that we want to make a “landVehicle” class, by which I mean somethign that could discuss land vehicles like cars, trucks, tanks, whatever.
Aspects of Land Vehicles
- They have variable speeds to drive at
- They have an external color
- They can drive different directions
So, if we had a game that needed land vehicles in it, we may want to write a class that describes them, so that the game can display them or use them somehow. The first two describe an specific attribute of the land vehicle, while the third one refers to something it can do. In a class, those first two could be stored as variables, and the third one could be used as a method, to cause the vehicle to drive a certain direction. We’ve covered methods before, so I am going to discuss some of the details about variables below.
In Objective-C, variables, in the end, are stored as something called a field. A field is the simplest way to store a variable, you basically just say what type of variable it is, and its name. There is also a slightly more advanced version of storing variables, that is a wrapper over a field, to give you a bit more control, this one is called a property. If you know a bit about Java, a property is basically the getters and setters that one would write to use a field. In general, one should use properties when storing a variable in Objective-C. It allows you to add code between the actual setting or getting of an object, instead of giving direct access of it to whatever calls the for the variable. This could be used for many things, like refusing to take a speed value greater than 100 for your land vehicle, assuming 100 was its top speed. Here is an example of a property, with its backing field used in a simple program.
@interface landVehicle()
@property (strong, nonatomic) NSString *color;
@end
@implementation landVehicle
@synthesize color = _color; //This tells it to generate the setters and getters, and tells them to point to a field named _color
-(NSString *)color
{
return _color;
}
-(void)setColor:(NSString *)color
{
_color = color;
}
@end
As stated in the comments, the @synthesize generates the setter and getter, but it does so invisibly to the code writer. You don’t normally see these, but this is what it generates under the hood. However, if you wanted to override the defaults (which are basically what you see here), you would write the one you wanted to override like this, and add your code as appropriate.
The actual creation of the property (the @property line) has a few unfamiliar things in it. Firstly, this is an object, and so what this actually is, is a pointer to a place in memory where the object is, which is signified by that asterisk.
The “strong” refers to how it will be memory managed. Basically, if an field has no strong pointers to it, it is deleted from memory. From my experience so far, most properties should be set to “strong”. One reason to use a “weak” pointer, is to avoid something called a “retain cycle”, which would be a time when two strong pointers refer to each other, like a parent object having a strong pointer to a child object, and the child object having a strong pointer to a parent object. Again, I’m still new, so I haven’t run in to this yet, but that is what I’ve read so far about it.
The “nonatomic” is something to say that the property is not thread-safe. I have even less experience with this one, but basically if you have a multithreaded program, and 2 or more threads wanted to read or write to the same property at the same time, the program needs to treat the properties in a special way, to keep things consistent and less crash inducing. For instance, if you had a string that stored the value “Pumpernickel”, and one thread wanted to change it to “Baguette”, and another thread wanted to read that variable at almost the same time, without locking, the one reading it might get “Baguernickel”, since it was in the process of writing it. I have not tested this (I don’t really know multithreaded programming in Objective-C, yet), and this may not be how a string is actually modified, but this is more to explain why you might lock it to have it wait until the write operation is complete. Atomic should make sure you either get “Pumpernickel” or “Baguette”, depending on if the call to the getter happens during the write, or shortly thereafter. If you want to read more about the difference this StackOverflow answer explains it quite nicely. Anyway, in general, until you start dealing with multiple threads, just use “nonatomic.”
A REALLY common reason to override the getter, is something that is called “lazy loading.” Below is an example of such, with an explanation after.
-(NSString *)color
{
if(!_color)
{
//_color = [[NSString alloc] init]; //General initialization
_color = @"Silver"; //Initialization with an NSString default
}
return _color;
}
What this basically adds, is that if _color is not initialized (or more specifically, if it IS equal to nil), then set to the default color of “Silver” as a string. In this case, there is a short cut for initialization of a string, but the commented out line would be a more general form which would just create an empty NSString. This lets you load the actual field with an object only after it is needed, which keeps you from having to spread if(color != nil) everywhere, you can just put it right here and it will always respond with a valid object.
So, that is a bit more about classes and the usage of variables in Objective-C. Thanks for reading this post and stay tuned for more field notes from the Coding Explorer.