Self-Learning XCode/Objective-C: 'static' doesn't seem to mean what I *think* it means - objective-c

I'm working through examples in the book 'Visual Quick Start, Objective-C' by Holzner. I spend a lot of time with each example, getting the code debugged is the faster part, and then stepping through saying to myself why each line of code works, what each word in each line does and deciding why the author used one way of doing things versus another. Then I repeat the example with some story of my own. This seems to be a good way to move from being a structured programmer and to an oop-like one. It works with these examples because he just does one concept at a time. (I've worked part way through 2 other books and this idea did not work for me in those. Once I got confused by something, I just stayed confused. There were too many variables in the lengthier, more complex examples.)
In the current example (page 137), Holzner uses the word 'static'. I looked through examples in this book to decide what this word means. I also read the description in Bjarne Stroustrups' C++ Programming Language book (I understand that C++ and Objective-C are not exactly the same)
(Bjarne Stroustup p 145)
use a static variable as a memory,
instead of a global variable that 'might be accessed and corrupted by other functions'
Here is what I understand 'static' means as a result. I thought that meant that the value of a static variable would never change. I thought that meant it was like a constant value, that once you set it to 1 or 5 it couldn't be changed during that run.
But in this example piece of code, the value of the static variable does change. So I am really unclear on what 'static' means.
(Please ignore the 'followup question' I left commented in. I didn't want to change anything from my run, and risk creating a reading error
Thank you for any clues you can give me. I hope I didn't put too much detail into this question.
Laurel
.....
Program loaded.
run
[Switching to process 2769]
Running…
The class count is 1
The class count is 2
Debugger stopped.
Program exited with status value:0.
.....
//
// main.m
// Using Constructors with Inheritance
//Quick Start Objective C page 137
//
#include <stdio.h>
#include <Foundation/Foundation.h>
#interface TheClass : NSObject
// FOLLOWUP QUESTION - IN last version of contructors we did ivars like this
//{
// int number;
//}
// Here no curly braces. I THINK because here we are using 'static' and/or maybe cuz keyword?
// or because in original we had methods and here we are just using inheirted methods
// And static is more long-lasting retention 'wise than the other method
// * * *
// Reminder on use of 'static' (Bjarne Stroustup p 145)
// use a static variable as a memory,
// instead of a global variable that 'might be accessed and corrupted by other functions'
static int count;
// remember that the + is a 'class method' that I can execute
// using just the class name, no object required (p 84. Quick Start, Holzner)
// So defining a class method 'getCount'
+(int) getCount;
#end
#implementation TheClass
-(TheClass*) init
{
self = [super init];
count++;
return self;
}
+(int) getCount
{
return count;
}
#end
// but since 'count' is static, how can it change it's value? It doeeessss....
int main (void) {
TheClass *tc1 = [TheClass new] ;
printf("The class count is %i\n", [TheClass getCount]);
TheClass *tc2 = [TheClass new] ;
printf("The class count is %i\n", [TheClass getCount]);
return 0;
}

"static" is not the same thing as C++ "const". Rather it's a statement that a variable be declared only once and is to remain (hence static) in memory. Say you have a function:
int getIndex()
{
static int index = 0;
++index;
return index;
}
In this case the "static" tells the compiler to retain the index value in memory. Everytime its accessed it is changed: 1,2,3,... .
Compare this to:
int getIndex()
{
int index = 0;
++index;
return index;
}
This will return the same value each time as the index variable is being created each time: 1,1,1,1,1,... .

To clarify No one in particular's answer even further, a variable that is static will remain the same throughout all instances of objects, between method calls, etc.
For instance, declaring the following method:
- (int)getNumber {
static int number = 0;
return ++number;
}
will return 1, 2, 3, 4, etc., across all instances of the given class at any given time. Neat, eh?

static means many things in C / C++ / Objective-C.
Objective-C follows C closely. In C++, static means more things than in C / Objective-C. So, don't judge what static does in Obj-C by what Bjarne Stroustrup says (who is the inventor of C++).
In C and Objective-C, two main meanings of static are
For a variable / function in the file level, it makes a variable / function invisible from other translation units (i.e. other source files compiled into the same program.) It doesn't mean its constant.
For a variable declared inside a function, it makes a variable not to reside in a stack but in a more persistent location, as explained by no one in particular.
In C++, in addition to this meaning, a static member in a class means it belongs to the class, not to an instance. This meaning is completely unrelated to the other meaning; in the olden days, people didn't want to introduce more reserved words in the language, so they just abused the same reserved words in different contexts to mean completely unrelated things. Another notorious example is the usage of the word virtual.
In any case, static doesn't mean it's constant.
Anyway, in a programming language, a thing means whatever the implementers or the standard committee members decide it to mean. Therefore I find it always helpful to read the standard. Just look for the word static in that PDF. You'll learn everything about static keyword in the programming language C there.

Related

Objective-C: Working with static variables

Given the code below, the spaceship (only ever one in the program) checks to see if it can pay for a new part, and 'if (so)', builds it. When the payFor: message is sent, should the iVars be dealt with like below, or should the each transaction be a method like +(void)deduct: (ShipObject *) cost;, or should I use struct and use structure arithmetic?
# implementation Spaceship
+(void) payFor: (ShipObject) *shipObject
{
totalEnergy -= [shipObject energy];
totalCredits -= [shipObject credits];
totalSamples -= [shipObject samples];
}
+(void) buildShipObject: (ShipObject) *shipObject
{
if ([self canBuild: shipObject]) {
[self payFor: shipObject];
...
}
Thanks for any insights!
First, since the methods are class methods, not instance methods, I assume that variables not ivars, but static variables of some sort.
If payments with some, not all, forms of payment are to be allowed (say, only with energy and samples, but not credits) then you should use three different methods. Otherwise, your payFor method is very idiomatic to Objective C. Using C struct should be reserved for the rare situations where Objective C classes no longer provide adequate performance.
Consider making the spaceship a singleton, and use ivars: this may become handy if you decide to introduce more ships in the game, or do something that's easier done with objects (e.g. externalization of object's state).

Understanding self in Objective-C

The code below is from an iTunes U course on iPhone dev in Objective-C. I've read the Apple documentation and it's all very very clear with the exception of self. I sort of understand self to be a pointer to myself, but what exactly does that mean? In the code below what exactly does self mean? What is the difference between self.topSpeed and self.nearestWormhole in the implementation file or does self refer to the same thing on both occasions? Does self.topSpeed refer to Planet * and self.nearestWormhole refer to Wormhole * ? Thanks to anyone who answers, I've learned C and now trying to learn OOP so any input is appreciated.
(Header file)
#import "Vehicle.h"
#import "Planet.h"
#interface Spaceship : Vehicle
#property (nonatomic) double topSpeed;
- (void)orbitPlanet:(Planet *)aPlanet
atAltitude:(double)km;
#end
(Implementation file)
#import "Spaceship.h"
#interface Spaceship()
#property (nonatomic, strong) Wormhole *nearestWormhole;
#end
#implementation Spaceship
#synthesize topSpeed = _topSpeed;
#synthesize nearestWormhole = _nearestWormhole;
- (void)setTopSpeed:(double)speed
{
if ((speed < 1) && (speed > 0)) _topSpeed = speed;
}
- (void)orbitPlanet:(Planet *)aPlanet atAltitude:(double)km
{
double speed = self.topSpeed;
if (speed > MAX_RELATIVE) speed = MAX_RELATIVE;
[self.nearestWormhole travelToPlanet:aPlanet
atSpeed:speed];
}
#end
self (or this in C++) refers to the object which is executing the method (or "on which the method is being invoked").
Suppose I have a room with three people, Arthur, Betty, and Ziggy, and a box of hats. We also define that
Arthur's teacher is Betty.
Betty's teacher is Ziggy.
Ziggy does not have a teacher.
I want to give the following set of instructions to all three people:
1. Put a hat on Ziggy's head.
This is pretty easy. "Ziggy" means the same person to Arthur, Betty, and even Ziggy. No matter who follows this instruction the same person receives the hat.
2. Put a hat on the head of your teacher, if you have one.
This instruction will have a different effect depending on who's following it, because teacher refers to someone different for each of the three. But each can ask him/herself "who is my teacher, if I have one?" and find that person.
But the next thing I want is for Arthur to put a hat on Arthur's head, Betty to put a hat on Betty's head, and Ziggy to put a hat on Ziggy's head. We can't refer to that person by name (like Ziggy) because it depends on who is doing it. Suppose we treat it like "teacher" and establish a variable "foo" such that Arthur's foo is Arthur, and Betty's foo is Betty… but it should be obvious that the idea we are really expressing is that Ziggy's foo is Ziggy, and Jack's foo would be Jack, and Skip's foo would be Skip… do we really need to establish a "foo"? No! Everyone has a foo: it's your self. So let's define an implicit variable "self" that is not declared anywhere but always refers to the person carrying out the action.
3. Put a hat on the head of your self.
This works for Arthur, Betty, Ziggy, and even Jack. It works for anyone.
In your code self refers to the Spaceship whose topSpeed needs to be accessed. You create many Spaceships and each needs to know the topSpeed of that one Spaceship which exists (we know it does because it's calling the method) but has no name (like myWingman.topSpeed) - one's self.
Cristian, I'll offer you a different tack on this. You say you know C, let's start there. If you needed to implement fractions you'd use a struct, and let's assume for some reason you decide to dynamically allocate your fractions. You have something like this:
typedef struct { int numerator; int denominator; } Fraction;
Fraction *newFraction(int numer, int denom)
{
Fraction *result = (Fraction *)malloc(sizeof(Fraction)); // allocate
result->numerator = numer;
result->denominator = denom;
return result;
}
Fraction *multiplyFraction(Fraction *left, Fraction *right)
{
Fraction *result = (Fraction *)malloc(sizeof(Fraction)); // allocate
result->numerator = left->numerator * right->numerator; // multiple (ignoring reduction)
result->denominator = left->denominator * right->denominator;
return result;
}
And you'd use it like:
Fraction *half = newFraction(1, 2);
Fraction *twothirds = newFraction(2, 3);
Fraction *onethird = multiplyFraction(half, twothirds); // results is 2/6 as we don't reduce in this example
This is the ADT - abstract data type - style of programming. You declare a data type whose content is private (the "abstract" part) to the functions you will provide, and a bunch of functions.
At the basic level what object-oriented programming does is just invert the way you look at this. Instead of "call function multiplyFraction passing two fractions" you say "pass the message multiplyFraction, along with a fraction, to a fraction". Using Objective-C syntax the last line above:
Fraction *onethird = multiplyFraction(half, twothirds);
becomes:
Fraction *onethird = [half multiplyFraction:twothirds];
Under the hood this "method send" just becomes a "function call" - Objective-C does a bit of work to locate multipleFraction and then calls it passing it both half and twoThirds.
Almost there! Now to match the changed syntax for the call Objective-C also changes the syntax of the definition of multiplyFraction:
- (Fraction *) multiplyFraction:(Fraction *)right
{
Fraction *result = [Fraction new]; // allocate
result->numerator = ????->numerator * right->numerator;
result->denominator = ????->denominator * right->denominator;
return result;
}
But what do you write for ????. As you'll see the syntax only names the second parameter (right), there is no name given for the first (which was left). Objective-C hides the passing of this parameter, every method takes at least one parameter - it is the "object" (rather than "ADT") that the method is sent to. It needs a name so you can refer to it, that name is self:
- (Fraction *) multiplyFraction:(Fraction *)right
{
Fraction *result = [Fraction new]; // allocate
result->numerator = self->numerator * right->numerator;
result->denominator = self->denominator * right->denominator;
return result;
}
And this is essentially it - self is the name of the first argument.
Object-oriented languages build upon this base, for example:
they had direct access to "instance" variables - the "fields" of the original struct;
they change some more syntax - e.g. #interface... replaces struct...; and rather than list the methods (functions) after the type (struct) in the header they are listed inside of it (the `#interface);
they usually add inheritance (though some ADT languages have that as well);
etc.
But under the hood an Objective-C class is implemented as a C struct...
HTH
Objective C emphasizes using getters and setters. To make things simpler, it even generates getters and setters when you #synthesize something.
So
self.topSpeed
accesses the getter for topSpeed. If you omit the "self" part, then it is equivalent to accessing the instance variable(ivars) directly (bad practice).
The reason for having a underscore before the variable name is also to make a clear differentiation between instance variable and the getter for the instance variable. This way, we cannot accidentally refer to topSpeed without "self".
You need to use self to access variable in all places except:
init
dealloc
Hope that helps.
self is indeed a pointer reference to the instance of the class that is running the code. In this case, self would be a reference to an instance of the Spaceship class.
When you reference self in a class method (which is very possible and an acceptable behavior), you are actually referencing a singleton instance representing the class. You can also get this singleton instance by calling [Spaceship class]. In practice, you'd use self like this mostly in factory methods when you need to allocate a new instance.
What you seem more confused about is syntax regarding other classes. You asked:
Does self.topSpeed refer to Planet * and self.nearestWormhole refer to
Wormhole * ?
Wormhole *nearestWormhole represents an instance of the Wormhole class, named nearestWormhole. So, when you use self.nearestWormhole, that is a pointer to a instance of the Workhole class. Inside the Spaceship class you could actually use _nearestWormhole or self.nearestWormhole to access that pointer. Other classes might call something like spaceship.nearestWormhole, which is using the accessor.
'self' refers to the instance of the current class, i.e. in your example it would refer to an instance of the Spaceship class. Because 'self' always refers to an instance of the class, it's not possible to call upon self in class methods.

Why would you use an ivar?

I usually see this question asked the other way, such as Must every ivar be a property? (and I like bbum's answer to this Q).
I use properties almost exclusively in my code. Every so often, however, I work with a contractor who has been developing on iOS for a long time and is a traditional game programmer. He writes code that declares almost no properties whatsoever and leans on ivars. I assume he does this because 1.) he's used to it since properties didn't always exist until Objective C 2.0 (Oct '07) and 2.) for the minimal performance gain of not going through a getter / setter.
While he writes code that doesn't leak, I'd still prefer him to use properties over ivars. We talked about it and he more or less sees not reason to use properties since we weren't using KVO and he's experienced with taking care of the memory issues.
My question is more... Why would you ever want to use an ivar period - experienced or not. Is there really that great of a performance difference that using an ivar would be justified?
Also as a point of clarification, I override setters and getters as needed and use the ivar that correlates with that property inside of the getter / setter. However, outside of a getter / setter or init, I always use the self.myProperty syntax.
Edit 1
I appreciate all of the good responses. One that I'd like to address that seems incorrect is that with an ivar you get encapsulation where with a property you don't. Just define the property in a class continuation. This will hide the property from outsiders. You can also declare the property readonly in the interface and redefine it as readwrite in the implementation like:
// readonly for outsiders
#property (nonatomic, copy, readonly) NSString * name;
and have in the class continuation:
// readwrite within this file
#property (nonatomic, copy) NSString * name;
To have it completely "private" only declare it in the class continuation.
Encapsulation
If the ivar is private, the other parts of the program can't get at it as easily. With a declared property, the clever people can access and mutate quite easily via the accessors.
Performance
Yes, this can make a difference in some cases. Some programs have constraints where they can not use any objc messaging in certain parts of the program (think realtime). In other cases, you may want to access it directly for speed. In other cases, it's because objc messaging acts as an optimization firewall. Finally, it can reduce your reference count operations and minimize peak memory usage (if done correctly).
Nontrivial Types
Example: If you have a C++ type, direct access is just the better approach sometimes. The type may not be copyable, or it may not be trivial to copy.
Multithreading
Many of your ivars are codependent. You must ensure your data integrity in multithreaded context. Thus, you may favor direct access to multiple members in critical sections. If you stick with accessors for codependent data, your locks must typically be reentrant and you will often end up making many more acquisitions (significantly more at times).
Program Correctness
Since the subclasses can override any method, you may eventually see there is a semantic difference between writing to the interface versus managing your state appropriately. Direct access for program correctness is especially common in partially constructed states -- in your initializers and in dealloc, it's best to use direct access. You may also find this common in the implementations of an accessor, a convenience constructor, copy, mutableCopy, and archiving/serialization implementations.
It's also more frequent as one moves from the everything has a public readwrite accessor mindset to one which hides its implementation details/data well. Sometimes you need to correctly step around side effects a subclass' override may introduce in order to do the right thing.
Binary Size
Declaring everything readwrite by default usually results in many accessor methods you never need, when you consider your program's execution for a moment. So it will add some fat to your program and load times as well.
Minimizes Complexity
In some cases, it's just completely unnecessary to add+type+maintain all that extra scaffolding for a simple variable such as a private bool that is written in one method and read in another.
That's not at all to say using properties or accessors is bad - each has important benefits and restrictions. Like many OO languages and approaches to design, you should also favor accessors with appropriate visibility in ObjC. There will be times you need to deviate. For that reason, I think it's often best to restrict direct accesses to the implementation which declares the ivar (e.g. declare it #private).
re Edit 1:
Most of us have memorized how to call a hidden accessor dynamically (as long as we know the name…). Meanwhile, most of us have not memorized how to properly access ivars which aren't visible (beyond KVC). The class continuation helps, but it does introduce vulnerabilities.
This workaround's obvious:
if ([obj respondsToSelector:(#selector(setName:)])
[(id)obj setName:#"Al Paca"];
Now try it with an ivar only, and without KVC.
For me it is usually performance. Accessing an ivar of an object is as fast as accessing a struct member in C using a pointer to memory containing such a struct. In fact, Objective-C objects are basically C structs located in dynamically allocated memory. This is usually as fast as your code can get, not even hand optimized assembly code can be any faster than that.
Accessing an ivar through a getter/setting involves an Objective-C method call, which is much slower (at least 3-4 times) than a "normal" C function call and even a normal C function call would already be multiple times slower than accessing a struct member. Depending on the attributes of your property, the setter/getter implementation generated by the compiler may involve another C function call to the functions objc_getProperty/objc_setProperty, as these will have to retain/copy/autorelease the objects as needed and further perform spinlocking for atomic properties where necessary. This can easily get very expensive and I'm not talking about being 50% slower.
Let's try this:
CFAbsoluteTime cft;
unsigned const kRuns = 1000 * 1000 * 1000;
cft = CFAbsoluteTimeGetCurrent();
for (unsigned i = 0; i < kRuns; i++) {
testIVar = i;
}
cft = CFAbsoluteTimeGetCurrent() - cft;
NSLog(#"1: %.1f picoseconds/run", (cft * 10000000000.0) / kRuns);
cft = CFAbsoluteTimeGetCurrent();
for (unsigned i = 0; i < kRuns; i++) {
[self setTestIVar:i];
}
cft = CFAbsoluteTimeGetCurrent() - cft;
NSLog(#"2: %.1f picoseconds/run", (cft * 10000000000.0) / kRuns);
Output:
1: 23.0 picoseconds/run
2: 98.4 picoseconds/run
This is 4.28 times slower and this was a non-atomic primitive int, pretty much the best case; most other cases are even worse (try an atomic NSString * property!). So if you can live with the fact that each ivar access is 4-5 times slower than it could be, using properties is fine (at least when it comes to performance), however, there are plenty of situations where such a performance drop is completely unacceptable.
Update 2015-10-20
Some people argue, that this is not a real world problem, the code above is purely synthetic and you will never notice that in a real application. Okay then, let's try a real world sample.
The code following below defines Account objects. An account has properties that describe name (NSString *), gender (enum), and age (unsigned) of its owner, as well as a balance (int64_t). An account object has an init method and a compare: method. The compare: method is defined as: Female orders before male, names order alphabetically, young orders before old, balance orders low to high.
Actually there exists two account classes, AccountA and AccountB. If you look their implementation, you'll notice that they are almost entirely identical, with one exception: The compare: method. AccountA objects access their own properties by method (getter), while AccountB objects access their own properties by ivar. That's really the only difference! They both access the properties of the other object to compare to by getter (accessing it by ivar wouldn't be safe! What if the other object is a subclass and has overridden the getter?). Also note that accessing your own properties as ivars does not break encapsulation (the ivars are still not public).
The test setup is really simple: Create 1 Mio random accounts, add them to an array and sort that array. That's it. Of course, there are two arrays, one for AccountA objects and one for AccountB objects and both arrays are filled with identical accounts (same data source). We time how long it takes to sort the arrays.
Here's the output of several runs I did yesterday:
runTime 1: 4.827070, 5.002070, 5.014527, 5.019014, 5.123039
runTime 2: 3.835088, 3.804666, 3.792654, 3.796857, 3.871076
As you can see, sorting the array of AccountB objects is always significant faster than sorting the array of AccountA objects.
Whoever claims that runtime differences of up to 1.32 seconds make no difference should better never do UI programming. If I want to change the sorting order of a large table, for example, time differences like these do make a huge difference to the user (the difference between an acceptable and a sluggish UI).
Also in this case the sample code is the only real work performed here, but how often is your code just a small gear of a complicated clockwork? And if every gear slows down the whole process like this, what does that mean for the speed of the whole clockwork in the end? Especially if one work step depends on the output of another one, which means all the inefficiencies will sum up. Most inefficiencies are not a problem on their own, it's their sheer sum that becomes a problem to the whole process. And such a problem is nothing a profiler will easily show because a profiler is about finding critical hot spots, but none of these inefficiencies are hot spots on their own. The CPU time is just averagely spread among them, yet each of them only has such a tiny fraction of it, it seems a total waste of time to optimize it. And it's true, optimizing just one of them would help absolutely nothing, optimizing all of them can help dramatically.
And even if you don't think in terms of CPU time, because you believe wasting CPU time is totally acceptable, after all "it's for free", then what about server hosting costs caused by power consumption? What about battery runtime of mobile devices? If you would write the same mobile app twice (e.g. an own mobile web browser), once a version where all classes access their own properties only by getters and once where all classes access them only by ivars, using the first one constantly will definitely drain the battery much faster than using the second one, even though they are functional equivalent and to the user the second one would even probably even feel a bit swifter.
Now here's the code for your main.m file (the code relies on ARC being enabled and be sure to use optimization when compiling to see the full effect):
#import <Foundation/Foundation.h>
typedef NS_ENUM(int, Gender) {
GenderMale,
GenderFemale
};
#interface AccountA : NSObject
#property (nonatomic) unsigned age;
#property (nonatomic) Gender gender;
#property (nonatomic) int64_t balance;
#property (nonatomic,nonnull,copy) NSString * name;
- (NSComparisonResult)compare:(nonnull AccountA *const)account;
- (nonnull instancetype)initWithName:(nonnull NSString *const)name
age:(const unsigned)age gender:(const Gender)gender
balance:(const int64_t)balance;
#end
#interface AccountB : NSObject
#property (nonatomic) unsigned age;
#property (nonatomic) Gender gender;
#property (nonatomic) int64_t balance;
#property (nonatomic,nonnull,copy) NSString * name;
- (NSComparisonResult)compare:(nonnull AccountB *const)account;
- (nonnull instancetype)initWithName:(nonnull NSString *const)name
age:(const unsigned)age gender:(const Gender)gender
balance:(const int64_t)balance;
#end
static
NSMutableArray * allAcocuntsA;
static
NSMutableArray * allAccountsB;
static
int64_t getRandom ( const uint64_t min, const uint64_t max ) {
assert(min <= max);
uint64_t rnd = arc4random(); // arc4random() returns a 32 bit value only
rnd = (rnd << 32) | arc4random();
rnd = rnd % ((max + 1) - min); // Trim it to range
return (rnd + min); // Lift it up to min value
}
static
void createAccounts ( const NSUInteger ammount ) {
NSArray *const maleNames = #[
#"Noah", #"Liam", #"Mason", #"Jacob", #"William",
#"Ethan", #"Michael", #"Alexander", #"James", #"Daniel"
];
NSArray *const femaleNames = #[
#"Emma", #"Olivia", #"Sophia", #"Isabella", #"Ava",
#"Mia", #"Emily", #"Abigail", #"Madison", #"Charlotte"
];
const NSUInteger nameCount = maleNames.count;
assert(maleNames.count == femaleNames.count); // Better be safe than sorry
allAcocuntsA = [NSMutableArray arrayWithCapacity:ammount];
allAccountsB = [NSMutableArray arrayWithCapacity:ammount];
for (uint64_t i = 0; i < ammount; i++) {
const Gender g = (getRandom(0, 1) == 0 ? GenderMale : GenderFemale);
const unsigned age = (unsigned)getRandom(18, 120);
const int64_t balance = (int64_t)getRandom(0, 200000000) - 100000000;
NSArray *const nameArray = (g == GenderMale ? maleNames : femaleNames);
const NSUInteger nameIndex = (NSUInteger)getRandom(0, nameCount - 1);
NSString *const name = nameArray[nameIndex];
AccountA *const accountA = [[AccountA alloc]
initWithName:name age:age gender:g balance:balance
];
AccountB *const accountB = [[AccountB alloc]
initWithName:name age:age gender:g balance:balance
];
[allAcocuntsA addObject:accountA];
[allAccountsB addObject:accountB];
}
}
int main(int argc, const char * argv[]) {
#autoreleasepool {
#autoreleasepool {
NSUInteger ammount = 1000000; // 1 Million;
if (argc > 1) {
unsigned long long temp = 0;
if (1 == sscanf(argv[1], "%llu", &temp)) {
// NSUIntegerMax may just be UINT32_MAX!
ammount = (NSUInteger)MIN(temp, NSUIntegerMax);
}
}
createAccounts(ammount);
}
// Sort A and take time
const CFAbsoluteTime startTime1 = CFAbsoluteTimeGetCurrent();
#autoreleasepool {
[allAcocuntsA sortedArrayUsingSelector:#selector(compare:)];
}
const CFAbsoluteTime runTime1 = CFAbsoluteTimeGetCurrent() - startTime1;
// Sort B and take time
const CFAbsoluteTime startTime2 = CFAbsoluteTimeGetCurrent();
#autoreleasepool {
[allAccountsB sortedArrayUsingSelector:#selector(compare:)];
}
const CFAbsoluteTime runTime2 = CFAbsoluteTimeGetCurrent() - startTime2;
NSLog(#"runTime 1: %f", runTime1);
NSLog(#"runTime 2: %f", runTime2);
}
return 0;
}
#implementation AccountA
- (NSComparisonResult)compare:(nonnull AccountA *const)account {
// Sort by gender first! Females prior to males.
if (self.gender != account.gender) {
if (self.gender == GenderFemale) return NSOrderedAscending;
return NSOrderedDescending;
}
// Otherwise sort by name
if (![self.name isEqualToString:account.name]) {
return [self.name compare:account.name];
}
// Otherwise sort by age, young to old
if (self.age != account.age) {
if (self.age < account.age) return NSOrderedAscending;
return NSOrderedDescending;
}
// Last ressort, sort by balance, low to high
if (self.balance != account.balance) {
if (self.balance < account.balance) return NSOrderedAscending;
return NSOrderedDescending;
}
// If we get here, the are really equal!
return NSOrderedSame;
}
- (nonnull instancetype)initWithName:(nonnull NSString *const)name
age:(const unsigned)age gender:(const Gender)gender
balance:(const int64_t)balance
{
self = [super init];
assert(self); // We promissed to never return nil!
_age = age;
_gender = gender;
_balance = balance;
_name = [name copy];
return self;
}
#end
#implementation AccountB
- (NSComparisonResult)compare:(nonnull AccountA *const)account {
// Sort by gender first! Females prior to males.
if (_gender != account.gender) {
if (_gender == GenderFemale) return NSOrderedAscending;
return NSOrderedDescending;
}
// Otherwise sort by name
if (![_name isEqualToString:account.name]) {
return [_name compare:account.name];
}
// Otherwise sort by age, young to old
if (_age != account.age) {
if (_age < account.age) return NSOrderedAscending;
return NSOrderedDescending;
}
// Last ressort, sort by balance, low to high
if (_balance != account.balance) {
if (_balance < account.balance) return NSOrderedAscending;
return NSOrderedDescending;
}
// If we get here, the are really equal!
return NSOrderedSame;
}
- (nonnull instancetype)initWithName:(nonnull NSString *const)name
age:(const unsigned)age gender:(const Gender)gender
balance:(const int64_t)balance
{
self = [super init];
assert(self); // We promissed to never return nil!
_age = age;
_gender = gender;
_balance = balance;
_name = [name copy];
return self;
}
#end
Semantics
What #property can express that ivars can't: nonatomic and copy.
What ivars can express that #property can't:
#protected: public on subclasses, private outside.
#package: public on frameworks on 64 bits, private outside. Same as #public on 32 bits. See Apple's 64-bit Class and Instance Variable Access Control.
Qualifiers. For example, arrays of strong object references: id __strong *_objs.
Performance
Short story: ivars are faster, but it doesn't matter for most uses. nonatomic properties don't use locks, but direct ivar is faster because it skips the accessors call. For details read the following email from lists.apple.com.
Subject: Re: when do you use properties vs. ivars?
From: John McCall <email#hidden>
Date: Sun, 17 Mar 2013 15:10:46 -0700
Properties affect performance in a lot of ways:
As already discussed, sending a message to do a load/store is slower than just doing the load/store inline.
Sending a message to do a load/store is also quite a bit more code that needs to be kept in i-cache: even if the getter/setter
added zero extra instructions beyond just the load/store, there'd be a
solid half-dozen extra instructions in the caller to set up the
message send and handle the result.
Sending a message forces an entry for that selector to be kept in the method cache, and that memory generally sticks around in
d-cache. This increases launch time, increases the static memory
usage of your app, and makes context switches more painful. Since the
method cache is specific to the dynamic class for an object, this
problem increases the more you use KVO on it.
Sending a message forces all values in the function to be spilled to the stack (or kept in callee-save registers, which just means
spilling at a different time).
Sending a message can have arbitrary side-effects and therefore
forces the compiler to reset all of its assumptions about non-local memory
cannot be hoisted, sunk, re-ordered, coalesced, or eliminated.
In ARC, the result of a message send will always get retained, either by the callee or the caller, even for +0 returns: even if the
method doesn't retain/autorelease its result, the caller doesn't know
that and has to try to take action to prevent the result from getting
autoreleased. This can never be eliminated because message sends are
not statically analyzable.
In ARC, because a setter method generally takes its argument at +0, there is no way to "transfer" a retain of that object (which, as
discussed above, ARC usually has) into the ivar, so the value
generally has to get retain/released twice.
None of this means that they're always bad, of course — there are a
lot of good reasons to use properties. Just keep in mind that, like
many other language features, they're not free.
John.
The most important reason is the OOP concept of information hiding: If you expose everything via properties and thus make allow external objects to peek at another object's internals then you will make use of these internal and thus complicate changing the implementation.
The "minimal performance" gain can quickly sum up and then become a problem. I know from experience; I work on an app that really takes the iDevices to their limits and we thus need to avoid unnecessary method calls (of course only where reasonably possible). To aid with this goal, we're also avoiding the dot syntax since it makes it hard to see the number of method calls on first sight: for example, how many method calls does the expression self.image.size.width trigger? By contrast, you can immediately tell with [[self image] size].width.
Also, with correct ivar naming, KVO is possible without properties (IIRC, I'm not an KVO expert).
Properties vs. instance variables is a trade-off, in the end the choice comes down to the application.
Encapsulation/Information Hiding This is a Good Thing (TM) from a design perspective, narrow interfaces and minimal linkage is what makes software maintainable and understandable. It is pretty hard in Obj-C to hide anything, but instance variables declared in the implementation come as close as you'll get.
Performance While "premature optimisation" is a Bad Thing (TM), writing badly performing code just because you can is at least as bad. Its hard to argue against a method call being more expensive than a load or store, and in computational intensive code the cost soon adds up.
In a static language with properties, such as C#, calls to setters/getters can often be optimised away by the compiler. However Obj-C is dynamic and removing such calls is much harder.
Abstraction An argument against instance variables in Obj-C has traditionally been memory management. With MRC instance variables require calls to retain/release/autorelease to be spread throughout the code, properties (synthesized or not) keep the MRC code in one place - the principle of abstraction which is a Good Thing (TM). However with GC or ARC this argument goes away, so abstraction for memory management is no longer an argument against instance variables.
Properties expose your variables to other classes. If you just need a variable that is only relative to the class you're creating, use an instance variable. Here's a small example: the XML classes for parsing RSS and the like cycle through a bunch of delegate methods and such. It's practical to have an instance of NSMutableString to store the result of each different pass of the parse. There's no reason why an outside class would need to ever access or manipulate that string. So, you just declare it in the header or privately and access it throughout the class. Setting a property for it might only be useful to make sure there are no memory issues, using self.mutableString to invoke the getter/setters.
Backwards compatibility was a factor for me. I couldn't use any Objective-C 2.0 features because I was developing software and printer drivers that had to work on Mac OS X 10.3 as part of a requirement. I know your question seemed targeted around iOS, but I thought I'd still share my reasons for not using properties.

Static variable in objective c

I am somewhat confused about memory allocation of static variable in objective C.
should we allocate memory for static variable using alloc:? and
initialize it usinginit:?
Is objective c static variable same as c static variable?
is it worth to apply retain on static variable?
There are a couple of things you need to take into account.
First, static C-like variables inside functions are technically fine. This should be:
- (void) f
{
static NSString* s = nil;
if (s == nil) {
s = [[NSString alloc] initWithString:#"Hello"];
}
}
The problem is that you will probably never be able to release, since s scope is only f function.
This is exactly like a C static variable inside a function.
There is also static usage to control visibility of a variable in a translation unit. So, if you want to only allow some variable to be accessed within file.c, just like C, you need to write in that file:
static NSString *s = [[NSString alloc] initWithString:#"Hello"];
Again, unless you write a specific method to release when you application ends, it will probably leak memory.
Finally, you can have "object oriented like" static behavior. You don't use static keyword here but as most object oriented languages, you can have class variables (in Java, C#, C++ and others, class variables are accomplished with the static keyword).
I only have answers to the first two of your questions — because I don't understand what you mean by your third one.
Let me start with question 2.:
Is objective c static variable same as c static variable?
Objective C (ObjC) is, basically, just plain-old-C (POC) — and a nifty dynamic runtime, that adds a lot of fancy.
This means that every C language qualifier (e.g. static) works in ObjC exactly like it would in POC.
So the answer to that question is: yes.
With that cleared, back to number one:
should we allocate memory for static variable using alloc:? and initialize it usinginit:?
The important thing about ObjC you need to always be aware of is, that there are no stack objects:
Every object you'll ever use lives on the heap.
From that follows that it is irrelevant in which scope (be it stack-local, static or global) you declare your object-type variables, in general, they will always be effectively alloc/inited.
There is one exception to these rules:
Blocks at least start out as stack variables — but those are funny creatures, anyway.
So, to answer this question: You actually don't have a choice!
Aside
if you're using statics for objects other than literal NSStrings — which might well be totally reasonable — consider wrapping them with a proper class-method, for sanity's sake.
This is a nice way of doing it:
+ (NSNumber *)theMagicNumber
{
static NSNumber *magicNumber;
static dispatch_once_t numberSemaphore;
dispatch_once( &numberSemaphore, ^{
magicNumber = [NSNumber numberWithInt:3]; // 1
[magicNumber retain]; // 2
} );
return magicNumber;
}
Notes:
As you probably know +[NSNumber numberWithInt:] returns an autoreleased object!
Since we want to hold on to this object, we need to retain it, as usual — or compile our code using ARC and get rid of lines like this, altogether!
I hope this example answers or at least helps you figuring out the answer to your last question.

Objective C: Initializing static variable with static method call

The Compiler claims an error saying: "initializer element is not constant", when I try to initialize a static variable inside a method with a call to a static method (with + in its definition).
Anyway I can tell him that this method always returns the same value. I know this is not the same as static method, but there seems to be no constant methods in Objective-C (other than macros which won't work here because I am calling UI_USER_INTERFACE_IDIOM() from inside the method).
There's actually another solution in addition to Yuji's. You can create a function and prefix it with a GCC attribute (also works in Clang and LLVM) that will cause it to be executed before main() is. I've used this approach several times, and it looks something like this:
static NSString *foo;
__attribute__((constructor)) initializeFoo() {
foo = ...;
}
When you actually use foo, it will already be initialized. This mean you don't have to check whether it's nil each time. (This is certainly a minor performance benefit, though multiplied by the number of times you use it, but it can also simplify one or more other regions of code. For example, if you reference the static variable in N different places, you might have to check for nil in all N or risk a crash. Often, people call a function or use a #define to handle initialization, and if that code is only actually used once, it can be a penalty worth removing.
You cannot do that in Objective-C.
There are two solutions:
Switch to Objective-C++. Change the file extension from .m to .mm.
Initialize it with nil, and check it when you first use it, as in:
static NSString*foo=nil;
if(!foo){
foo=[ ... ] ;
}