views:

1076

answers:

5

I'm new to Objective-C and Cocoa. I've read that NSInteger and NSNumber are preferred when working with simple integers because they're the "platform-safe" versions of the primitive numeric types (and in NSNumber's case, wrapped in an object). So, I need a counter in my class that gets incremented when an NSTimer fires. On an Apple forum I found a group of people all recommending to someone in a similar situation that they should declare a NSNumber pointer in the header, initialize it with numberWithInt:, and then each time it needs to be incremented do so by assigning it to a new object (something like counter = [NSNumber numberWithInt:[counter intValue]+1];). This looks like overkill to me. If all I need is an int counter (and btw, I'm resetting it back to 0 after it hits 15 so size isn't an issue), can't I get away with just using an int and not have to allocate a new object with each iteration of my timer's loop?

And if so, how do I make a primitive type available throughout my class. I know that with object types, I declare it in my interface and use @property and @synthesize...what's the equivalent (if one exists) when working with primitives?

+10  A: 

Using NSNumber for a simple counter does look a little bit of over kill. You can declare class members as NSInteger and simply update them using ++ or +=

for example:

@interface YourViewController : UIViewController  {
NSInteger counter;  
}

@property (nonatomic,assign) NSInteger counter;

The @synthesize is just:

@synthesize counter

and can be incremented either by:

self.counter += 1;

or

counter ++;

the later will prevent any observers from being informed, thus might not be preferable.

Gareth Davis
I didn't know that += worked on properties... thanks to @gs
Gareth Davis
+8  A: 

NSNumber is an object representation of a number. I use it when storing numbers in a collection class because they can only hold object pointers.

So in your example, which needs a counter, it probably is overkill.

NSInteger is simply an integer that is typedefed to be safe for 32 and 64 bit programs, and is recommended by Apple for use instead of int. It is not an object. This is probably what you need for a counter (actually NSUInteger, which is an unsigned int) might be better.

As for making primitives available throughout your class - well, if you declare it in the header as an iVar, it is available throughout your class anyway. @property and @synthesize are just Objective-C 2.0 ways of declaring these as properties that can be seen (and perhaps changed) outside of your class in a KVC/KVO compliant manner. Primitive types can be used as properties using the same @property and @synthesize syntax.

Abizern
+4  A: 

I use NSInteger (not int, to be more portable), and wrap it into a NSNumber if I need to add it to a collection (such as a NSMutableDictionary when saving the state on quitting the application).

pgb
+1  A: 

I agree with your instinct, using an object for a simple counter sounds like overkill and will add an unnecessary number of message dispatch calls for simply incrementing a counter. For a counter that doesn't need to be stored in a collection or manipulated as an object, stick with C scalar types.

To declare a scalar as an instance variable of your class, just declare it in your header file:

@interface MyClass: NSObject{
  int counter;
}

@end
gbc
A: 

If you do need to increment an NSNumber (such as for an NSManagedObject property) I found this category helped:

@interface NSNumber (Incrementer)
- (NSNumber *)increment;
@end

@implementation NSNumber (Incrementer)
- (NSNumber *)increment {
    return [NSNumber numberWithInt:[self intValue]+1];
}
@end

so you can simplify the increment statements to:

counter = [counter increment];
Chris Miles