views:

291

answers:

5

Hi there,

I'm still getting confused by Objective-C. Sometimes you declare a variable like so:

NSRect rect;

And sometimes like so:

NSValue *value;

I never know when to add the *, so far I always looked it up in Apple's documentation. I know the difference is between a value and a pointer to an object.

But are there any hard and fast rules as to when I declare a value and when I declare a pointer? Something to make it easier to remember? Or do I have to know (eg. look up) which NSSomething is a value and which is an object?

Thank you!

+5  A: 

If the variable is a pointer to an object, you use *. An exception is id (which has an implied *). Things like NSRect and NSRange are just structures wrapped around basic C variables.

You won't necessarily be able to tell what an unknown NS____ is, but then you wouldn't really want to be using it without looking up the documentation and finding out how to use it anyway. As long as you understand the rules behind it, I wouldn't worry about it too much - you will soon pick up which things are which.

wipolar
Note you can always Command-double-click a keyword to see its definition in the header file, or Option-Command-double-click it to see its documentation.
Rob Keniger
+5  A: 

Short and simple: yes, you have to remember this for each type, but it will come very naturally after a little while.

It's not so much a question of "which NSSomething is a value and which is an object" (more accurately: which NSSomething is a scalar datatype or a struct and which is a class), though. Even though you won't see or use declarations like:

NSRect *pointerToARect;
NSInteger *pointerToAnInteger;

very often, they are perfectly valid and necessary at times. So for scalars (simple datatypes like NSInteger) and structs, both variants are valid and which one you use depends on whether you need a pointer or the actual thing.

With objects, all your variables must always be pointers because objects can only be allocated on the heap and not on the stack. So unlike the examples above, this:

NSValue myValue; // invalid!

is not correct and will not compile.

Ole Begemann
+1  A: 

The general rule of using the * in my case is when I'm using one of Apple's built in classes/frameworks. Anything you need to run alloc; and init: is something you hold a reference to, not the actual thing (like an int, or float value).

Jessedc
+1  A: 

As found in the Foundation Reference, the following are data types and are therefore structures. You need to declare these as values.

   * NSAppleEventManagerSuspensionID
   * NSByteOrder
   * NSComparator
   * NSComparisonResult
   * NSDecimal
   * NSEnumerationOptions
   * NSHashEnumerator
   * NSHashTable
   * NSHashTableCallBacks
   * NSHashTableOptions
   * NSInteger
   * NSMapEnumerator
   * NSMapTable
   * NSMapTableKeyCallBacks
   * NSMapTableOptions
   * NSMapTableValueCallBacks
   * NSPoint
   * NSPointArray
   * NSPointPointer
   * NSRange
   * NSRangePointer
   * NSRect
   * NSRectArray
   * NSRectEdge
   * NSRectPointer
   * NSSearchPathDirectory
   * NSSearchPathDomainMask
   * NSSize
   * NSSizeArray
   * NSSizePointer
   * NSSocketNativeHandle
   * NSSortOptions
   * NSStringEncoding
   * NSSwappedDouble
   * NSSwappedFloat
   * NSTimeInterval
   * NSUncaughtExceptionHandler
   * NSUInteger
   * NSZone

Response to Sherman: You're right, I didn't look through the list carefully - a minority of the definitions were indeed not structures. However, these data types are not referenced as pointers: for example, you'll never use "NSRangePointer *".

Response to bbum: Even though you could explicitly allocate memory on the heap for these structures and reference it through a pointer, it is bad practice in Cocoa.

Vector Maniac
No you don't. Any one of those could be used through a pointer.
bbum
Data type does not imply structure. All structures are data types, but not all data types are structures.For example, `NSUInteger` is a typedef, which aliases another type. NSRangePointer is also a typedef for a pointer to an NSRange structure. Some of those could be enumerated types or typedefs, depending on the SDK you're compiling against.Obj-C classes are also types.
Jeremy W. Sherman
+1  A: 

You don't use an asterisk for NSRect because it's just a C struct and not an Objective-C class. Many of the Foundation primitives are structs, like NSPoint and NSRange. You can hold Option and double-click on a type to bring up its documentation, or hold Command and double-click to go to its header definition and see for yourself what it is.

If you're not familiar with C and pointers, I highly recommend learning them first since Objective-C is just C with objects and a messaging system, and much of Objective-C will then make sense to you.

Preston