Mutable array object types [duplicate] - objective-c

This question already has answers here:
NSMutableArray - force the array to hold specific object type only
(12 answers)
Closed 9 years ago.
I'm programming on Objective C for the first time, coming from C++ (so far I like
the latter much better!). I have a question regarding mutable arrays, namely I want to create one with the specific type of one of my objects, 'CMParticle', instead of the generic ID type. To access data in my object from my mutable array, I have to cast it as one of my objects each time (which is I believe cumbersome) like so:
rij[0] = ((CMParticle *)particles[*pi]).crds[0] - ((CMParticle *)particles[*pj]).crds[0];
where 'particles' is my mutable array of CMParticle objects. I would rather do this
rij[0] = particles[*pi].crds[0] - particles[*pj].crds[0];
Prior to this I declare my mutable array like so:
particles = [NSMutableArray array];
It would be nice if I could declare this array with my type somehow so I don't have to typecast every time. Is there a way to do this?

What you're trying to do doesn't actually make sense in Objective C.
C++ containers are homogenous, but generic. You can have a vector<CMParticle>, or a vector<int>, and they're different types.
ObjC containers are heterogeneous. You just have an NSArray, and it can hold CMParticle objects, NSNumber objects, or anything else, all mixed up in one big array.
You generally don't need these casts at all. If you want to send a message to my_array[3], just do [my_array[3] doSomething:15]. Just like a higher-level language (Python, Ruby, Smalltalk, Javascript, etc.).
The only problem is that (unlike Python, etc.), there are a few cases where you do need the cast. Most critically (and annoyingly), if you want to access members directly, you have to cast first. This is one of the reasons that ObjC (unlike Python, etc.) encourages you to use #property and/or explicit accessors instead of directly accessing members. (Also, as a more minor annoyance, because variables have declared types, you can't just write tempval = my_array[3];, you have to specify the type, like: CMParticle *tempval = my_array[3].)
Another way to look at this: C++ extends C's static, weak type system to give you a stronger static type system; ObjC instead bolts on a separate dynamic type system (unfortunately leaving the existing C stuff unchanged, which is where the occasional problems come in).
You can pretty easily write your own NSMutableArray subclass that's generic (taking the class at runtime, unlike C++'s compile time, of course) and homogenous, but all that does is add restrictions; the elements will still be id everywhere. The only way around that is to write a custom class for each array: MutableCMParticleArray, MutableNSNumberArray, etc.

Related

What is the actual difference between an 'object' and a 'variable' in 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.

Objective-C Containers that take objects

I'm doing my first steps in objective-c (after a long, long time away from it) by translating some Java code I wrote for an Android game. It seems like there is no container that can take an object, without casting it to id first? Or is there?
Specifically this is the code I'm trying to work with:
NSMutableArray *touchedBodies = [[NSMutableArray alloc] init];
// some additional code
if(![touchedBodies containsObject:(id)body]) {
[touchedBodies addObject:(id)body];
}
The containsObject line passes fine, but on the touchedBodies addObject:(id)b I'm getting a "bad access" error. The body I'm trying to add is a legitimate Box2D b2Body.
When I tried to add the body directly, without casting it:
[touchedBodies addObject:body];
the compiler complains "Cannot initialize a parameter of type id with an lvalue of type b2Body* '
What am I missing?
First of all you never need to cast to an id type just because you can consider id as the Object class in Java: it's an implicit upcast that doesn't need to be explicit.
In second instance the problem occurs because 2dBody is a C++ class, not an Objective-C class. While you can mix Objective-C++ and C++ code (the former is a superset of the latter), you can't mix objects from these two languages without some workarounds.
You have mainly three solutions:
if 2dBody is a pointer, wrap it inside an NSValue: [touchedBodies addObject:[NSValue valueWithPointer:body]], this introduces some overhead with object allocations and you will need to cast it when you use it, 2dBody *b = (2dBody*)[value pointerValue]
if 2dBody is not a pointer then you could use an NSData: [NSData dataWithBytes:.. length:..], this introduces overhead, problems with memory management (unless you use noCopy variants), it introduces problems if the layout of the class is not standard, and you will need to cast it in any case
forget cocoa collections and use STL collections, they're more performant and they will manage everything seamlessly: vector<2dBody> touchedBodies; touchedBodies.push_back(body);.
I strongly suggest using STL collections, I personally use this approach

What is the -> operator doing in -copyWithZone:? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Arrow operator (->) usage in C
Dot (“.”) operator and arrow (“->”) operator use in C vs. Objective-C
I'm a newbie looking at a freeware/open-source program last updated in 2008, and I don't recognize the -> in the following notation:
- (id)copyWithZone:(NSZone *)zone
{
GFIPGeniusItem * newItem = [[[self class] allocWithZone:zone] init];
newItem->_stringValue = [_stringValue copy];
newItem->_imageURL = [_imageURL copy];
newItem->_webResourceURL = [_webResourceURL copy];
newItem->_speakableStringValue = [_speakableStringValue copy];
newItem->_soundURL = [_soundURL copy];
return newItem;
}
I'm assuming it's allowing some sort of shortcut, but I'd love to specifically what it does.
It's a way to directly access an instance variable within an ObjC object from outside that object. (The syntax and -> is borrowed from C structs, behaving as if the reference were a pointer-to-structure).
This access mechanism is almost vestigial at this point, and very uncommonly seen in modern ObjC code, because good encapsulation requires the use of accessors and properties, not touching instance variables directly. It's legitimate in some very special cases, though, and this is one of them:
When copying an object, you want to get a resulting copy that matches exactly the state of the current self. The cleanest way of achieving this is often to set the copy's ivars explicitly, to prevent any side-effects that the init overloads or accessors might cause. It's "safe" because the code doing it is still located within the class that's in question, so if you needed to change or add ivars, you could update this code as well with the knowledge of anything else that might require.
Doing this from outside the class in question is bad form, and there's no good reason to do it.
In Objective-C you have some kind of two variable type accessors. The one everybody should know is the "." one (e.g. Class.variable). This type calls either the appropriate getter or setter.
Now, the other type - the one you asked for - is for in-class usage. Obviously, as the getter or setter gets called automatically with the "." notation you need a way to set the variable without a setter (calling the setter in the setter itself results in an endless loop). Therefore, this "->" notation is used -> simply, it is the direct-access mode.
Usually, Objective-C the variable name for both notations is the same but some prefer to have the in-class notation variable name beginning with "_". This is achieved by editing the #synthesize variable line to #synthesize variable = _variable.
That's a pointer indirection operator. a->b means the same thing as (*a).b (where the . is the structure member access operator, not Objective-C's property dot syntax).
When you say:
newItem->_stringValue
you're directly accessing the _stringValue instance variable of the object to which newItem points.
The -> operator is very common in C++, but not so much in Objective-C.
In Objective C, like in C++, the p->m notation is equivalent to (*p).m This is, the dereference of the pointer to the base type followed by a call to the corresponding method or property.
So in your case, using the other notation it would look like this:
(*newItem)._stringValue = [_stringValue copy];
(It's more common to use the -> operator)

Why is it a pointer? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
objective c difference between id and void *
why most of the objects we create in iphone are pointers
According to Stanford university course, 2010/2011
Lecture 3
The guy made something strange there (at least for me), which is that
NSString *digit = sender.titlelabel.text;
Why is digit a pointer?
The type of your digit is id, which is just basically just a C pointer to a certain struct. All references to objects in Objective-C have this primitive type, regardless of the Class of the object. So the answer to your question is, unfortunately, because that's the way Objective-C works.
So whether you're declaring an NSString*, or an UITableViewController*, or MyClass*, your variable has type id. This is the primary means by which the language implements polymorphism. So, for example, the following declarations are equivalent:
NSString *digit;
id digit;
And it's true of method prototypes as well. These are equivalent:
-(UITableViewCell *)tableView:(UITableView)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-(id)tableView:(id)tableView cellForRowAtIndexPath:(id)indexPath;
A variable of type id is not an object itself, it is a pointer to an object. It is the handle with which you manipulate an object. Objective-C does all of the class compatibility work at runtime.
Hope this helps. Any questions?
Updates
That's right: int, float, double, char, void, and the pointer combinations, are all C primitive types. You can and will still use these quite a bit, and they are just what they are in a C program. But Objective-C adds the id type as a way to bridge the gap between the primitive typing of C and the very high-level typing of objects by the Objective-C system. id itself is typedef'd as a pointer to a simple struct in objc.h. At the level of the compiler and the language itself, there really isn't too much meaning to the type. For example, you'll almost never declare an array of ids, certainly never perform any arithmetic with them.
In fact, it's not too far a stretch to say that Objective-C is just plain vanilla C with some added syntax (particularly, the square-bracket notation for method invocation), a few extra primitive types (id, IMP, SEL), and a big runtime library. It's this runtime library that handles all things Object-Oriented.
Anyway, to answer your question, when you're actually programming, you will most often (99% of the time) just use class names to declare your variables - NSString *, NSData *, UITableViewController *, and so on. And the compiler will know what you're talking about, and issue a warning if you write code that clearly tries to put an NSString* where an NSData* is expected. But the actual meaning of those types really exists only at runtime.
I've digressed a little, but I'm not sure where your understanding is failing you, so I thought I'd just explain things a bit. You might want to read Apple's The Objective-C Programming Language to get a feel for the language.
NSString is an Objective-C class and all object references in Objective-C are pointers. I would suggest reading through some of the documentation such as Learning Objective-C A Primer:
Notice the * in the first declaration. In Objective-C, object
references are pointers. If this doesn’t make complete sense to you,
don’t worry—you don’t have to be an expert with pointers to be able to
start programming with Objective-C. You just have to remember to put
the * in front of the variable names for strongly-typed object
declarations. The id type implies a pointer.
It's not a digit, it's the "text" from the label, which is (I'm guessing) a string of integers and such to express the time.
So, all NSString types are declared as pointers in Obj-c.
sender.titlelabel.text;
Returns a NSString *
Remember, it's the same as:
NSString *str = [sender.titlelabel getText];
Because text is too. Or more preceisly, because the getText message returns a pointer.
You can find an intersting about why it has to be a pointer:
NSString and Pointers
I Hope it will help you to understand it in a Objective-C way.

Dot (".") operator and arrow ("->") operator use in C vs. Objective-C

I'm trying to wrap my head around some of the differences in usage and syntax in C vs. Objective-C. In particular, I want to know how (and why) the usage differs for the dot operator and the arrow operator in C vs. Objective-C. Here is a simple example.
C Code:
// declare a pointer to a Fraction
struct Fraction *frac;
...
// reference an 'instance' variable
int n = (*frac).numerator; // these two expressions
int n = frac->numerator; // are equivalent
Objective-C Code:
// declare a pointer to a Fraction
Fraction *frac = [[Fraction alloc] init];
...
// reference an instance variable
int n = frac.numerator; // why isn't this (*frac).numerator or frac->numerator??
So, seeing how frac is the same in both programs (i.e. it is a pointer to a Fraction object or struct), why are they using different syntax when accessing properties? In particular, in C, the numerator property is accessed with frac->numerator, but with Objective-C, it is accessed using the dot operator, with frac.numerator. Since frac is a pointer in both programs, why are these expressions different? Can anyone help clarify this for me?
frac is actually not the same in both programs.
A C Fraction is a struct, which is a base type with no overloaded operators and is only really able to be constructed and destructed by default. If you define functions or fields on the struct, the way to access those properties in C is with the dot (.) operator. Objective-C maintains this operator when you use structs. For convenience, you can perform a dereference-and-dot operation using the arrow (->) operator (the two equivalent expressions you mention). Objective-C also preserves this when accessing structs.
An Objective-C Fraction in your example, however, is probably (one would assume) a pointer of at least type id, which is simply a classname and pointer to the instance of that class under the hood. It's also very likely to be a subclass of NSObject or NSProxy. These Objective-C classes are special in that they have a whole layer of predefined operations on top of just a C struct (if you really want to dig into it then you can take a look at the Objective-C Runtime Reference). Also important to note, an Objective-C class is always a pointer.
One of the most basic operations is objc_msgSend. When we operate on these types of objects, the Objective-C compiler interprets a dot (.) operator or the square bracket syntax ([object method]) as an objc_msgSend method call. For more detailed info about what actually happens here, see this series of posts by Bill Bumgarner, an Apple engineer who oversees the development of the Obj-C runtime.
The arrow (->) operator is not really supposed to be used on Objective-C objects. Like I said, Objective-C class instances are a C struct with an extra layer of communication added, but that layer of communication is essentially bypassed when you use the arrow. For example, if you open up Xcode and type in [UIApplication sharedApplication]-> and then bring up the method completion list, you see this:
Here you can see a bunch of normal fields which we generally access with square bracket syntax (like [[UIApplication sharedApplication] delegate]). These particular items, however, are the C fields that store the values of their respective Objective-C properties.
So, you can roughly think of it like this:
Dot operator on a C object
(at run time) Return value of the field
Arrow operator on a C object (pointer)
Dereference pointer
Return value of the field
Dot operator/square brackets on an Objective-C object (pointer)
(at compile time) Replace with call to objc_msgSend
(at run time) Look up Obj-C class definition, throw exception if something went wrong
Dereference pointer
Return value of the field
Arrow operator on an Objective-C object (pointer)
(at run time) Dereference pointer
Return value of the field
Now I'm definitely oversimplifying here, but to summarise: the arrow operators appear to do basically the same thing in both cases, but the dot operator has an extra/different meaning in Objective-C.
Dot-notation is a design choice. Since we always deal with pointers to objc instances, I'd guess the designers wanted something familiar, which also would not break existing programs. It was introduced in ObjC 2 - just a few years ago. Before that, you always had to use brackets for messaging.
Dot notation makes a difference though - it is not direct access, but a message.
That is:
obj.property = val;
// is the same as:
[obj setProperty:val];
// and not:
obj->property = val;
val = obj.property;
// is the same as:
val = [obj property];
// and not:
val = obj->property;
You can still write obj->ivar to access a pointer to object's members (if visible).
In your first example, Fraction is a struct.
In your second example, Fraction is an Objective-C class (and in iOS would likely be a subclass of NSObject).
C++ does not allow overloading of operator .. Therefore without additional information you can deduce that the dot notation you're seeing is an additional language construct integrated into Objective-C, rather than a C/C++ defined or overloaded operator.
As it happens, the dot notation is simply a design feature the implementors chose as shorthand for property access, entirely equivalent to the square bracket getter:
myObjCVar.prop == [myObjCVar prop];
The dot operator on objects is a special syntax for accessing objects' properties. It calls the property's getter or setter behind the scenes. So, for example, [#"hello" length] and #"hello".length are equivalent*. For all other types, the dot is the same as the C dot, and the arrow is always the same.
* Note: The accessor method won't always be named the same as the property. If it's a declared property and the declaration designates a special getter or setter method, that one will be used instead.
The dot and arrow notation are equally the same in C as it is in Objective-C (strict superset of ). I think the fundamental difference that needs to be distinguished is the difference between a struct and an Objective-C object.
The dot notation used for objects in Objective-C are used for properties that was introduced in Objective-C 2.0. However, with structs, the -> and dot notation between Objective-C and C are the same.