What is the actual difference between an 'object' and a 'variable' in Objective-C? - objective-c

I would like to ask a question, about an 'Object' and 'variable' in Objective-C. As we know, we can take many variables to store data of an object, but first we have to create an object with allocation. We have to give a memory location for our object in RAM using 'alloc' keyword. I think object can't store data because, an object is a noun, like a person. So, to store a data we need to use a variable. In C or C++ we use a variable of any primitive data type for data storage purpose. In Objective-C we use predefined classes like NSString.
So, can I use a variable with my NSString class type or I will use only an object with class type object.
There are two problems for me.
NSString *xyz = [[NSString alloc] init]; // can anyone tell me what should be 'xyz' in here a 'variable' or an 'object'?
if 'xyz' is an object in here. So, firstly I have to create it. But somewhere I have seen like....
NSString *xyz = #"welcome"; // according to me, here we are not allocating memory for 'xyz'. Why?
What is the difference between both statements? Can you please tell me?

Objects are instances of classes. (And that's all there is. Nothing else needs saying).
Variables are global and static variables (having unlimited life times) and automatic variables (variables existing while a function is executing, or while a new scope in a function is entered), and disappearing when the scope ends or the function returns.
In Objective-C, objects can never be variables. Pointers to objects can be variables, but objects can't. Values that are part of an object are often called "instance variables", but that is not the same as a variable.
In other languages, like C++, objects can be variables. The question "what is the difference between objects and variables" doesn't really make sense. It's like asking "what's the difference between alcohol and a cow". They are different categories of things.
#"MyString" is a shortcut; the compiler will create an object for you and give you a pointer to that object.

Related

What does (NSString *)name mean?

I was going through an Objective-C book to learn, and came across a notation that I don't particularly recognize:
A pointer to "name" is created in the header as an instance variable.
NSString *name;
Then, in one of the function declarations, it says:
-(id)initWithName:(NSString*)name atFrequency:(double)freq;
I understand that this is an instance method called initWithName:atFrequency:, but I don't understand the meaning of the argument (NSString*)name.
Any help would he greatly appreciated!
The two things called name are utterly unrelated. One (the first) is, as you say, an instance variable. The other is a method parameter, a local reference to the first argument supplied in the method call. So if anyone ever says
[[MyClass alloc] initWithName:#"howdy" atFrequency:2];
then inside the body of the initWithName:atFrequency: method, there will be a variable name with a value #"howdy" (and a variable freq with a value 2.0).
However, this is frowned on. Your local variable is overshadowing an instance variable. That's unwise, and in fact I would expect the compiler to warn.

How to access a property/variable using a String holding its name

If I had two variables in Objective C like this where one holds the name of the other as a string
NSInteger result = 4;
NSString * theName = #"result";
How would I best access the first variable using the string instead of a reference to the variable? For instance if I had a lot of variables and would generate the name of the one I need by code I'd need a way to get to the variable using that string.
Though not directly answering your question, it's possible to access properties (or ivars) of an object by
[object setValue:#"value" forKey:theName]
Similarly, the getter is [object valueForKey:theName] (thanks kevboh!)
That's not possible in objective-c. Variable names cannot be synthesised by name. The variable name itself doesn't mean anything when running your code, the compiler converts it into a memory address. The name is just a way for the programmer to make writing and reading code easier.
Depends on your exact situation but you probably should be using an NSArray or NSDictionary.

Assigning object pointers

Is this pointer assignment correct?
customclass.somearray = &*otherarray;
where somearray and otherarray are NSArray objects.
If not, how do I solve my problem:
I want to share this otherarray object with customclass.somearray. And I want all changes
made to customclass.somearray to be made to the original otherarray too.
Doing it this way, it works. I just want to ask, is it correct?
Your two variables are pointers of the same type, so just assign one to the other:
customclass.somearray = otherarray;
The way you have written this is unnecessary. Using the dereference operator * essentially gives you the "contents" of the pointer. The address-of operator & correspondingly gives you the address of whatever you apply it to. Your pointer otherarray contains an address. If you dereference that address and then take the address of that, you end up right back where you started.
Be aware that the left side of this assignment is a property access (assuming that customclass is also an object and not just a struct). This means that the compiler will change your expression into:
[customclass setSomearray:&*otherarray];
// And my version will be changed into:
[customclass setSomearray:otherarray];
That is, it becomes a method call rather than a simple assignment. This does not affect the syntax you should use, however.
When working in Objective-C, you never deal with objects directly, but always refer to them via pointers. Always. In C++, you can declare an actual object on the stack, for example, but you never do that in Objective-C. So, if you have:
NSArray *otherArray = [NSArray arrayWithObjects:#"foo", #"bar", nil];
then otherArray is a pointer to an instance of NSArray. Likewise, your somearray property will be of type NSArray*, so the types will match and you can just assign one to the other:
customclass.somearray = otherarray;
Hope that helps.

How do you declare instance of the class in Objective C?

Let's imagine I have Fraction class. So, the correct way to create instance of it is:
Fraction *myFraction;
or
myFraction = Fraction;
or
myFraction = [Fraction new];
or something else?
In the book i'm studying the correct one is first, but it looks unreasonable to me. Why do we have to create a pointer for it? Why don't we make the real instance?
That first expression means - give me a pointer to the new instance of Fraction class, doesn't it?
The first declares a variable named myFraction of type Fraction *, but doesn't create anything, nor initialize myFraction. The second isn't valid. The third creates a new Fraction and assigns it to a previously declared variable named myFraction. Often in Objective-C, you'll declare and initialize a variable in a single statement:
Fraction *myFraction = [[Fraction alloc] init];
As for whether to use new or alloc followed by init, it's largely a matter of taste.
Variables for storing objects are pointers in part because Objective-C inherited C's call-by-value semantics. When one variable is assigned to another (such as when passing it to a function), the value will be copied. At best, this is inefficient for immutable objects. At worst, it leads to incorrect behavior. Pointers are a way around call-by-value and the copy-on-assign semantics: the value of a variable with pointer type is just the pointer. It can be copied without touching the target object. The cost for this is you need some form of memory management.
It would be a good idea to read Kernihan and Ritchie's "The C Programming Language" so you can get an idea about how variables are declared.
There are two modes of allocation in C and Obj-C and C++: manual and automatic.
Integers and floats and characters and such are generally automatically declared. They are created when the declaration passes (i.e. int i), and deleted when the scope they were created in goes away, i.e. when you exit the block in which they were declared. They're called automatics. (it's also possible to declare them "static" but for the purposes of this discussion regarding allocation, these are the same)
Objects are too complicated to pass around to functions, as function parameters are "pass by value", meaning that the parameter gets a copy of the value being passed in, instead of the variable itself. It'd take a huge amount of time to copy a whole object all the time.
For this reason, you want to just tell the various functions where they can find the object. Instead of handing off a copy of the object, you hand off a copy of the address of the object. The address is stored in an automatic with a type of pointer. (This is really just an integer, but it's size is dictated by the hardware and OS, so it needs to be a special type.)
The declaration Fraction *myFraction; means "myFraction is a pointer, and just so you know, it's going to point to a Fraction later."
This will automatically allocate the pointer, but not the whole Fraction. For that to happen, you must call alloc and init.
The big reason why you have this two step process is that since we typically want objects to stick around for a while, we don't want the system automatically killing them at the end of a function. We need them to persist. We create places to hang the object in our functions, but those hangers go away when they aren't needed. We don't want them taking the object with them.
Ultimately, you might make declarations like this:
Fraction *myFraction = [[Fraction alloc] initWithNumerator: 2 Denominator: 3];
which says: "Make me a Fraction, and set it to be 2/3, and then put the address of that Fraction into 'myFraction'."
Why do we have to create a pointer for it? Why don't we make the real instance?
In Objective-C, every object is pointer type. So, you need to use either new or alloc/init.
Fraction *myFraction = [ Fraction new ] ;
or
Fraction *myFraction = [ [Fraction alloc] init ] ;
And myFraction needs to be released.
That first expression means - give me a pointer to the new instance of Fraction class, doesn't it?
No, you are just declaring a pointer of type Fraction. And the second statement is not even valid.

Why are object variables declared with a star

This may seem like trivial question.
But why is that we have to use the asterisk symbol when declaring object variables
Like, we do
Car * mazda = [[Car alloc] init];
What's the importance of the asterisk, I mean the compiler already knows it's an object, I'm sure the compiler can be trained not to complain about it. But then again by omitting it, I get an error message "statically allocating instance of objective-c class NSObject" What purpose would that serve?
The asterix is a qualifier to the Car variable that you declaring. It means that you are declaring a pointer to a Car rather than declaring a Car itself. The return value of the init function (and the alloc function for that matter) is a pointer to a Car, not a Car itself, therefore this is correct.
With * you declare a pointer. That’s like in C, which is a subset of ObjC. Without the * the variable would be statically allocated which is not possible for ObjC objects (because the size of the object couldn’t be determined at compile time).
Statically allocated variables are used for primitive C types like int or double
int number = 42;
Objective-C requires that all objects are dynamically allocated (i.e. on the heap). The error you're getting indicates that you're trying to create a Car object on the stack. By declaring mazda to be a pointer to Car (Car*) rather than a Car, you satisfy that requirement.
This is effectively a dupe of Why [object doSomething] and not [*object doSomething]?, which has a ton of background information.
The asterix in variable declaration also means the value of the variable will not have a static allocated value. Its a pointer just like the others have said.