When to use NSInteger vs. int
You usually want to use NSInteger
when you don't know what kind of processor architecture your code might run on, so you may for some reason want the largest possible integer type, which on 32 bit systems is just an int
, while on a 64-bit system it's a long
.
I'd stick with using NSInteger
instead of int
/long
unless you specifically require them.
NSInteger
/NSUInteger
are defined as *dynamic typedef
*s to one of these types, and they are defined like this:
#if __LP64__ || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
With regard to the correct format specifier you should use for each of these types, see the String Programming Guide's section on Platform Dependencies
int vs NSNumber vs NSInteger
NSInteger
is a type definition that describes an integer - but it is NOT equivalent to int
on 64-bit platforms.
You can examine the typedef by cmd-clicking on NSInteger
in Xcode.NSInteger
is defined as int
when building a 32-bit app and as long
for 64-bit apps.
Most of the time you can replace int with NSInteger, but there are some things to consider when doing so.
Apple's 64-Bit Transition Guide for Cocoa has some information about that.
NSNumber is a class that helps you to store numeric types as object. It has methods to convert between different types and methods to retrieve a string representation of your numeric value.
If you use a variable day
of type NSNumber*
the way you did in your example, you are not modifying the value of day
but its memory address.
If you are working with time values you also could take a look at NSDate.
NSNumber vs Int
As a generalization: Just stick with POD types until you need to use an object based representation, such as NSNumber
. The performance is much better with the PODs, but you'll need NSNumber
in some cases.
In some cases, it may make sense to use NSNumber
instead -- this is typically when you reuse a NSNumber
often -- this is to avoid making a ton of duplicate NSNumber
s. Such occurrences are practical only rarely beyond serialization and generic objc interfaces (bindings, transformers, dictionaries).
Update/Details: The ObjC runtime will in some cases, on some architectures, and on some OS versions substitute a tagged pointer representing NSNumber
s of specific type and domain. Although the internal representation has changed since originally written a few years back, here is a good introduction to the subject: http://objectivistc.tumblr.com/post/7872364181/tagged-pointers-and-fast-pathed-cfnumber-integers-in. Where this can be used, it saves you from slow operations like allocations, locking, and ref count ops. Nevertheless, tagged pointers are incapable of representing every number and it introduces overhead, so you should still favor basic builtins over NSNumber
as a default. Tagged pointers are a great optimization where applicable, but are far from competing with the builtins when you just need a number.
Objective C - when to use NSNumber vs a Primitive
NSNumber
is somewhat rare in Objective-C. Certainly not unheard of, but somewhat rare. If you're in doubt, you want to use NSInteger
. I've written whole, large programs without a single NSNumber
in them.
The most common use for NSNumber
is when you want to put it into an NSArray
, NSDictionary
or serialize it (for example into NSUserDefaults
). Most of the time, numbers are just a property of some other object, as an NSInteger
.
What's the difference between NSNumber and NSInteger?
The existing answers are useful; adding to them:
Yes, NSUInteger
gives twice the range among positive integers as NSInteger
, but I think another critical reason to choose between the two is simply to distinguish among cases where negative values simply do not make sense.
Example: the return value of NSArray
's count
method is an NSUInteger
, which makes sense since we cannot have an array with a negative number of elements. When the coder knows it's unsigned, he/she has more freedom to perform operations that might be unreliable in the signed case, including bitwise operations such as shifting. This blog post talks more about signed vs unsigned.
My guess about CGFloat
vs NSFloat
(which doesn't exist): It might be the case that the designers of the NeXTStep-named code elements simply didn't need to specify too many float values, outside of time intervals. So they gave NSTimeInterval
, which is a floating-point type, but that is clearly intended for use with time intervals. And, frankly, it's great to have that type because you know it's always meant to be in seconds without having to deal with a struct. When you move into the graphics world (where Core Graphics lives), suddenly floats are all around you, hovering in the air (haha). So it makes sense to introduce a CGFloat
there. This paragraph is all "educated speculation."
Also, just to be clear about why you might use NSInteger
etc instead of primitive types: Because this way it's easier to write portable code that takes full advantage of the machine architecture. For example, a CGFloat
uses 32 bits on some machines and 64 bits on others, depending largely on how much of an efficiency gap there is on those machines for those sizes. In some cases, there's no real speedup for using 32 bits vs 64 bits, so you might as well use 64 bits. If you've declared things as CGFloat
's, you suddenly get that extra precision "for free" when you recompile.
And, as iKenndac has pointed out, NSNumber
is a wrapper class for all of these (and other primitive or quasi-primitive types like the BOOL
) which enables you to include it in your NSArray
s and NSDictionary
s, archive them more easily, and do other things that NSObject
s can do.
Benefits of using NSInteger over int?
I personally think that, 64-bit is actually the reason for existence for NSInteger and NSUInteger; before 10.5, those did not exist. The two are simply defined as longs in 64-bit, and as ints in 32-bit.
NSInteger
/NSUInteger
are defined as *dynamic typedef
*s to one of these types, and they are defined like this:
#if __LP64__ || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
Thus, using them in place of the more basic C types when you want the 'bit-native' size.
I suggest you to throughly read this link.
CocoaDev has some more info.
For proper format specifier you should use for each of these types, see the String Programming Guide's section on Platform Dependencies
NSInteger vs int vs object
It does sound like you've made it overly complex. Obviously, the idea is not really "there is a variable named totalSave
" since the user could care less about where you store it, and from the rest of your post, you actually don't care about how you store it.
That said, in order to make this a bit more concrete, let's think about a "total score" state that numerous parts of the program might add to. There are a couple of approaches you might take. In any case, you likely have some object somewhere that is keeping track of the score. We'll call it the Game
object, but it could be a Level
or whatever.
So there are three big schools of thought: you can pass this Game
object around to everyone, you can have a Game
singleton, or you can use notifications. Each of these approaches has advantages, and any one you pick is probably fine for a simple program (personally, for a very simple program, I'd use a singleton).
In the first scheme, at some point in the program you create a Game
object that has some addToScore:
method. You assign this object as a property on every other object that needs to update the score. Each of those calls [self.game addToScore:value]
. This approach makes unit testing a bit simpler, but can be a bit tedious to implement.
In the second scheme, you have some shared singleton +[Game sharedGame]
. When you want to update the score, call [[Game sharedGame] addToScore:value]
. This is generally the easiet to implement.
In the third scheme, you have some object (Game
) that uses NSNotificationCenter
to observe some notification. When you want to update the score, you just post a notification that includes the amount to add in its user dictionary. This is great for keeping things extremely decoupled, but again can be a little tedious in the more usual case.
But as @Chuck notes, you're probably over-thinking this, and you may want to go back and work through some of the tutorials to get a better sense of how these things usually work. The kind of situation you're describing is not very complicated.
NSInteger vs 64-bit architecture on iOS
Your point about using types from the <stdint.h>
header of C99 is absolutely valid: these types give you more control over the size of your integral types. The NS
-prefixed integral types, however, predate the standardization of <stdint.h>
, hence introducing a parallel set of abstractions.
I use NS
-prefixed integral types when interacting with Cocoa methods. For example, if Cocoa method returns NSUinteger
, I declare my variable using NSUinteger
type as well.
I use <stdint.h>
types for variables in my program when I need precise control over the size of the stored data. Items that end up in Core Data are in this category.
When the size of an integral type does not matter, for example, when I need a loop control variable in a for
loop, I use int
.
Related Topics
Performselector May Cause a Leak Because Its Selector Is Unknown
How to Exit Iphone Application
How to Apply a Perspective Transform to a Uiview
How to Change the Name of an iOS App
Getting Current Device Language in Ios
Cfnetwork Sslhandshake Failed iOS 9
Remove HTML Tags from an Nsstring on the Iphone
Expand/Collapse Section in Uitableview in Ios
Evenly Space Multiple Views Within a Container View
How to Force a Uiviewcontroller to Portrait Orientation in iOS 6
Ios 9 Not Opening Instagram App With Url Scheme
How to Present Uialertcontroller When Not in a View Controller
How to Find Topmost View Controller on Ios
How to Adjust the Anchor Point of a Calayer, When Auto Layout Is Being Used