Static variable in objective c - 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.

Related

Automatically running a selector on instance creation

In Objective-C, is there any way to run a specific selector automatically every time an object is instantiated? (I know about +initialize but I need an instance method).
Specifically, I am writing a custom string class (that inherits from my own root class with a similar interface to NSObject) and I am trying to make it 'play nicely' with Objective-C constant strings. To do this, I have the following class definition (as required by the runtime):
// 1) Required Layout
#interface MYConstantString : MYObject {
//Class isa; inherited from MYObject
char *c_string;
unsigned int length;
}
Now, I want to implement my string class by using a pointer to a C-struct inside the class (this "C object" is already well implemented so I basically just want to wrap it in an Objective-C class). Ideally therefore, my Objective-C class would look like this:
// 2) Desired Laout
#interface MYConstantString : MYObject {
// Class isa;
StringObject *string;
}
And then the class and instance methods would just wrap C function calls using that StringObject.
So because I can't have the desired ivar layout (2), I wish to hack around the required ivar layout (1) to work for me. For example:
- (void)fixup {
// Pseudocode
temp = copystring(c_string);
c_string = (void *)StringObjectNewWithString(temp); // Fudge pointer
length = ... // I can do something else with this.
}
So, to return to the question, is there a way to call -fixup automatically, rather than having to do the following every time I make write an Objective-C constant string?
MYConstantString *str = #"Constant string";
[str fixup];
I know this is an obscene hack, and Objective-C constant string interoperability isn't totally crucial for what I need, but it would be nice to be able to use the #"" syntax and make the code more 'naturally' Objective-C.
I'm guessing you left out an important fact: you're using -fconstant-string-class=MYConstantString when building to have the compiler use your class for constant string objects (#"...").
Given that, then, no. There are two significant problems. First, "instance creation" for constant strings happens at compile time, not run time. The reason that there's a required layout is that the compiler does nothing but lay out the string's data in a data section with a reference to the appropriate class object where the isa pointer goes. It doesn't invoke any custom code. It is not necessarily even aware of such custom code at compile time. A given translation unit may not include the constant string class. The reference to that is resolved at link time.
Second, the constant string instance is almost certainly laid out in a read-only data section. There's a good chance that even calling your -fixup method manually as in your question would encounter an access violation because you'd be modifying read-only memory.
You should consider using a class cluster. Make MYConstantString one concrete subclass of an abstract base class. Make it conform to the required layout and just use the character pointer and length ivars as they are. If it would be convenient to translate to StringObject at various points, do that at those points. Implement other, separate concrete subclasses to use StringObject internally, if desired.
MYConstantString *str = #"Constant string";
That can't work because #"..." is an NSString, and it's not only a problem of layout but of instance sizes. If you want 0-copy or anything like that, what you have to do is have something like:
MYConstantString *str = [MyConstantString stringWithNSString:#"Constant string"];
and let -stringWithNSString: recognize when the passed string is a constant one (I'm pretty sure the concrete class of constant strings is easy to recognize, and probably hasn't changed ever for backward compatibility reasons) and then hack it around to grab the pointer to the bytes and similar things.

Does declaring a variable outside a loop in Objective-C have any optimising effect?

I have acquired the habit of declaring reused variables outside loops from having worked in Other Languages, like so:
NSString *lcword;
for( NSString *word in tokens )
{
lcword = [ word lowercaseString ];
...
}
Is it reasonable to do this in Objective-C also, or is the compiler smart enough to make it unnecessary?
There's no benefit in Objective-C that I know of. AFAIK every modern Objective-C compiler allocates the stack space for local variables at the beginning of the function or method. Scoping the variable to the loop just prevents you from using the name outside the loop and prevents the compiler from reusing the stack space if it wants to.
See also: Is there any overhead to declaring a variable within a loop? (C++) (It's about a different language, so I wouldn't mark it as a dupe, but the compiler techniques at work are very similar)
If you can reuse a variable then do it. No need to declare a new one each iteration if it's not needed.

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

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.

static NSStrings in Objective-C

I frequently see a code snippet like this in class instance methods:
static NSString *myString = #"This is a string.";
I can't seem to figure out why this works. Is this simply the objc equivalent of a #define that's limited to the method's scope? I (think) I understand the static nature of the variable, but more specifically about NSStrings, why isn't it being alloc'd, init'd?
Thanks~
I think the question has two unrelated parts.
One is why isn't it being alloc'ed and init'ed. The answer is that when you write a Objective-C string literal of the #"foo" form, the Objective-C compiler will create an NSString instance for you.
The other question is what the static modifier does. It does the same that it does in a C function, ensuring that the myString variable is the same each time the method is used (even between different object instances).
A #define macro is something quite different: It's "programmatic cut and paste" of source code, executed before the code arrives at the compiler.
Just stumbled upon the very same static NSString declaration. I wondered how exactly this static magic works, so I read up a bit. I'm only gonna address the static part of your question.
According to K&R every variable in C has two basic attributes: type (e.g. float) and storage class (auto, register, static, extern, typedef).
The static storage class has two different effects depending on whether it's used:
inside of a block of code (e.g. inside of a function),
outside of all blocks (at the same level as a function).
A variable inside a block that doesn't have it's storage class declared is by default considered to be auto (i.e. it's local). It will get deleted as soon as the block exits. When you declare an automatic variable to be static it will keep it's value upon exit. That value will still be there when the block of code gets invoked again.
Global variables (declared at the same level as a function) are always static. Explicitly declaring a global variable (or a function) to be static limits its scope to just the single source code file. It won't be accessible from and it won't conflict with other source files. This is called internal linkage.
If you'd like to find out more then read up on internal and external linkage in C.
You don't see a call to alloc/init because the #"..." construct creates a constant string in memory (via the compiler).
In this context, static means that the variable cannot be accessed out of the file in which it is defined.
For the part of NSString alloc, init:
I think first, it can be thought as a convenience, but it is not equally the same for [[NSString alloc] init].
I found a useful link here. You can take a look at that
NSString and shortcuts
For the part of static and #define:
static instance in the class means you can access using any instance of the class. You can change the value of static. For the function, it means variable's value is preserved between function calls
#define is you put a macro constant to avoid magic number and string and define function macros. #define MAX_NUMBER 100. then you can use int a[MAX_MUMBER]. When the code is compiled, it will be copied and pasted to int a[100]
It's a special case init case for NSString which simply points the NSString pointer to an instance allocated and inited at startup (or maybe lazily, I'm not sure.) There is one one of these NSString instances created in this fashion for each unique #"" you use in your program.
Also I think this is true even if you don't use the static keyword. Furthermore I think all other NSStrings initialized with this string will point to the same instance (not a problem because they are immutable.)
It's not the same as a #define, because you actually have an NSString variable by creating the string with the = #"whatever" initialization. It seems more equivalent to c's const char* somestr = "blah blah blah".

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=[ ... ] ;
}