incorrect variable value outside main() - objective-c

i have this code
#import <Foundation/Foundation.h>
int testint;
NSString *teststring;
int Test()
{
NSLog(#"%d",testint);
NSLog(#"%#",teststring);
}
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
testint = 5;
NSString *teststring = [[NSString alloc] initWithString:#"test string"];
Test();
[pool drain];
return 0;
}
in output i have:
5
(null)
why Test function doesn't see correct teststring value? What should I do, to have correct "test string" in output?

You're shadowing a global variable with a local one. If the intent is to use the global testString, you shouldn't re-declare it with "NSString*".

in output i have:
5 (null)
why Test function doesn't see correct teststring value?
Because you never assigned anything there. In main, you declared a local variable with the same name, and initialized that variable with the pointer to the NSString object you created.
how should i declare global objects with "alloc init"?
You don't.
Declarations create variables (or sometimes types). The NSString *teststring lines (both of them) are declarations: One of a global variable, the other of a local variable.
alloc messages (and most other messages to classes) create objects.
Thus, this line:
NSString *teststring = [[NSString alloc] initWithString:#"test string"];
declared a local variable (teststring) and created a string object, and initialized the variable to hold the pointer to the string object.
(Note that “initWithString:” initializes the object, not the variable. The part from the = until the semicolon is the initializer for the variable.)
You meant to assign to the global variable, not declare a local variable. So, do that: Leave out the type specifier to turn the declaration into an assignment statement:
teststring = [[NSString alloc] initWithString:#"test string"];
By the way, you don't need to use alloc and initWithString: here. #"test string" is already an NSString object. And when you do alloc something, don't forget to release it (assuming you didn't turn on the GC).

You have two different variables named testint. The one in main() is shadowing the global one.

how should i declare global objects with "alloc init"?
Strings are a special case. You can do this:
NSString* foo = #"bar";

Related

Pointer Variable (*) and Double Pointer (**) Usage With Classes in Objective C

int a=1;
int * b;
b = &a;
int **c=&b;
In Objective-C, the Pointer (*) variable is used for primitive data types as well with classes like NSString, NSError etc...
NSString *str = #"iOS"; // or NSString *str= [[NSString alloc] initWithString : #"iOS"];
NSArray *arr =[[NSArray alloc] init];
I have seen in Objective-C (NSError **) what is use of double pointer objects for classes in Objective-C?
There is no such thing as a "double pointer". If you call it a "double pointer", you are just getting yourself confused.
Write a function that should return two ints. You can't have two return values, so you write
void f (int* result1, int* result2)
{
*result1 = 1;
*result2 = 2;
}
Now write a function that should return two NSString*. That should make it obvious.

Is it a variable or an object? Im very confused

#import <Foundation/Foundation.h>
int main (int argc, char * argv[])
{
#autoreleasepool {
NSString *str = #"Programming is fun";
NSLog (#"%#", str);
}
return 0;
}
In the line
NSString *str = #"Programming is fun";
the constant string object Programming is fun is assigned to the NSString variable str. Its value is then displayed using NSLog .
The NSLog format characters %# can be used to display not just NSString objects, but other objects as well.
/*****/
The previous paragraph was from a book I read, what is really confusing to me is why is he keep using the words variable and objects interchangeably? are objects and varaibles the same thing? so far this is the only confusing part about obj-c to me.
please explain, thank you
An object is an instance of a class. Something that is allocated in memory.
A variable is a name which you use to access something like an object (NSString for example) or a primitive (int for example).
In your case so your object is an instance of NSString, that contains #"Programming is fun":
NSString *str = #"Programming is fun";
The variable to access that object is str.

Why does a string pointer in Objective-C accept and return the value of the string and not a memory address?

For example in this code:
NSString *greeting = #"Hello";
NSLog(#"Greeting message: %#\n", greeting );
Greeting takes the value of a string, not an address. It also displays a string in NSLog and not an address. However, I thought pointers were supposed to be used like this:
int var = 20; /* actual variable declaration */
int *ip; /* pointer variable declaration */
ip = &var; /* store address of var in pointer variable*/
NSLog(#"Address of var variable: %x\n", &var );
/* address stored in pointer variable */
NSLog(#"Address stored in ip variable: %x\n", ip );
/* access the value using the pointer */
NSLog(#"Value of *ip variable: %d\n", *ip );
return 0;
I've always wondered why it's okay to do this with string pointers.
Well, that is something called Syntactic Sugar. What we are actually seeing; exactly doesn't happen like that under the hood.
For example, the code you have written:
NSString *greeting = #"Hello";
NSLog(#"Greeting message: %#\n", greeting );
When you pass greeting into NSLog, actually the following line of code gets executed.
NSLog(#"Greeting message: %#\n", [greeting description]); // description is a method defined in NSObject and NSString inherits it.
And even if you do:
NSString *greeting = #"Hello";
Now, greeting variable doesn't hold the contents of the string, neither it can because it is a pointer. It just holds the address of NSString #"Hello" where it is stored. And again, the assignment of pointer happens under the hood. The same is the case with the C language; we can write the following code in C, and it will compile without any errors:
char *string = "Hello, world!";
In C, the string "Hello, world!" is basically a character array, and string variable actually stores the pointer to this character array.
If you see the definition of NSLog method, it looks something like this:
FOUNDATION_EXPORT void NSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
It clearly shows that NSLog message receives an NSString pointer. But what do we actually pass? We pass the NSString in it, but what is actually passed is a pointer to that NSString, again under the hood :)
I hope this helps you.
%# is the string formatter for NSObjects, calling the objects -description method. If you want the pointer address of the string object try %p.
NSString *string = #"A string";
NSLog(#"Object contents: %#", string);
NSLog(#"Object address: %p", string);

Is it necessary to assign a string to a variable before comparing it to another?

I want to compare the value of an NSString to the string "Wrong". Here is my code:
NSString *wrongTxt = [[NSString alloc] initWithFormat:#"Wrong"];
if( [statusString isEqualToString:wrongTxt] ){
doSomething;
}
Do I really have to create an NSString for "Wrong"?
Also, can I compare the value of a UILabel's text to a string without assigning the label value to a string?
Do I really have to create an NSString for "Wrong"?
No, why not just do:
if([statusString isEqualToString:#"Wrong"]){
//doSomething;
}
Using #"" simply creates a string literal, which is a valid NSString.
Also, can I compare the value of a UILabel.text to a string without assigning the label value to a string?
Yes, you can do something like:
UILabel *label = ...;
if([someString isEqualToString:label.text]) {
// Do stuff here
}
if ([statusString isEqualToString:#"Wrong"]) {
// do something
}
Brian, also worth throwing in here - the others are of course correct that you don't need to declare a string variable. However, next time you want to declare a string you don't need to do the following:
NSString *myString = [[NSString alloc] initWithFormat:#"SomeText"];
Although the above does work, it provides a retained NSString variable which you will then need to explicitly release after you've finished using it.
Next time you want a string variable you can use the "#" symbol in a much more convenient way:
NSString *myString = #"SomeText";
This will be autoreleased when you've finished with it so you'll avoid memory leaks too...
Hope that helps!
You can also use the NSString class methods which will also create an autoreleased instance and have more options like string formatting:
NSString *myString = [NSString stringWithString:#"abc"];
NSString *myString = [NSString stringWithFormat:#"abc %d efg", 42];

Creating object named after the value of an NSString - is it possible?

Is it possible to create an object named after an NSString's value? If so, how?
Try this:
Class theClass = NSClassFromString(someString);
id object = [[theClass alloc] init];
If you mean that the string specifies the class name, then yes it's easy to do this using the NSClassFromString function to lookup the appropriate class "factory" object:
NSString* myClassName = #"NSNumber";
id myNewObject = [[NSClassFromString(myClassName) alloc] init];
// myNewObject is an NSNumber...
The example is contrived, but you get the idea.
Yes:
//In your header
extern NSString *FrobnitzerCalibrationHigh;
extern NSString *FrobnitzerCalibrationMedium;
extern NSString *FrobnitzerCalibrationLow;
//In your implementation
NSString *FrobnitzerCalibrationHigh = #"FrobnitzerCalibrationHigh";
NSString *FrobnitzerCalibrationMedium = #"FrobnitzerCalibrationMedium";
NSString *FrobnitzerCalibrationLow = #"FrobnitzerCalibrationLow";
You can make a couple of macros and put them in your prefix header:
//Semicolons intentionally omitted (see below)
#define DECLARE_STRING_CONSTANT(name) extern NSString *name
#define DEFINE_STRING_CONSTANT(name) NSString *name = ##name
Then use them in your class headers and implementations:
//In your header
DECLARE_STRING_CONSTANT(FrobnitzerCalibrationHigh);
DECLARE_STRING_CONSTANT(FrobnitzerCalibrationMedium);
DECLARE_STRING_CONSTANT(FrobnitzerCalibrationLow);
//In your implementation
DEFINE_STRING_CONSTANT(FrobnitzerCalibrationHigh);
DEFINE_STRING_CONSTANT(FrobnitzerCalibrationMedium);
DEFINE_STRING_CONSTANT(FrobnitzerCalibrationLow);
(The macros omit the semicolons because their usages will supply them. If the macros had semicolons as well, the expansion would be extern NSString *FrobnitzerCalibrationHigh;;—harmless in this case, but it would bug me if I did this, largely because it's not harmless in some other cases.)