-[NSSet containsObject:] returns NO when it should return YES

  • I'm trying to compare instances of NSNumber using NSSet.  I have a set of numbers, which represent 64-bit persistent IDs for iTunes media-items.  I access these values using the -[NSNumber longLongValue] method.  I'm adding them to an instance of NSSet and then use that instance to determine whether or not I've seen the given item before.

    The application is a black-list of songs and albums that want to avoid processing when scanning the iTunes library.  I find that the comparison does not always work when it should and I am at a loss to explain why.

    I assumed that the -[NSObject hash] method is used to determining equality and that to different NSNumber instances will hash out to the same value if they have the same 64-bit value stored inside.

    I also assumed that whether or not the value is signed or unsigned; negative or positive makes no difference as long as calling the same accessor method on both NSNumber instances returns the same result.

    It looks like at least one, maybe both of these assumptions are wrong.  Since I'm working with both Core Data and the MediaLibrary APIs on iOS, I'm a little wary of subclassing NSNumber in an attempt to fix the hash method.

    The following gdb console output demonstrates an instance of a media-item persistent-ID property that, when queried gives a large unsigned number.  When I ask again using the -longLongValue method, I get the answer I was expecting.  When I look inside the set, you will see that the value -1748299021286640132 is in the set.  However, when -containsObject is called, it returns NO.

    (gdb) po mediaItem
    <MPConcreteMediaItem: 0x6e752f0> 16698445052422911484
    (gdb) po [mediaItem persistentID]
    0x930bf5fc does not appear to point to a valid object.
    (gdb) po [mediaItem persistentIDProperty]
    16698445052422911484
    (gdb) p (NSNumber*) [mediaItem persistentIDProperty]
    $1 = (NSNumber *) 0x79681b0
    (gdb) p (long long)[$1 longLongValue]
    $2 = -1748299021286640132
    (gdb) po noPlaySongs
    {(
        -1748299021286641066,
        -1748299021286641065,
        -1748299021286640132
    )}
    (gdb) continue

    Anyone have previous experience with this problem?  Can you shed some light on where my thinking and assumptions are wrong.  I could write a sweet of tests to try and prove/disprove what I think is happening but I'm hoping to benefit from someone else's pre-existing research, experiments, or internal knowledge.

    My Google incantation did not yield any results, either.

    Thanks.

    -Michael
  • On Feb 19, 2011, at 3:17 PM, Michael Crawford wrote:

    > I assumed that the -[NSObject hash] method is used to determining equality and that to different NSNumber instances will hash out to the same value if they have the same 64-bit value stored inside.

    I'm pretty sure that, for instance, two calls to [NSNumber numberWithLongLong: 1] will produce two different objects, and though they may fall into the same hash bucket if the hash method uses the numeric value, they will still not be treated as the same object by -containsObject.

    If you look at the -member method instead, you'll see that it uses isEqual, so maybe that would do what you want, or maybe not, depending on how isEqual is implemented by NSNumber. -filteredSetUsingPredicate would seem to do it, but would be slower since it will iterate the whole set.

    Personally, though my approach may not be terribly popular with the Cocoa crowd, I'd use std::set ;-)

    --
    Scott Ribe
    <scott_ribe...>
    http://www.elevated-dev.com/
    (303) 722-0567 voice
  • On Feb 19, 2011, at 2:17 PM, Michael Crawford wrote:

    > I'm trying to compare instances of NSNumber using NSSet.  I have a set of numbers, which represent 64-bit persistent IDs for iTunes media-items.  I access these values using the -[NSNumber longLongValue] method.  I'm adding them to an instance of NSSet and then use that instance to determine whether or not I've seen the given item before.

    > Anyone have previous experience with this problem?  Can you shed some light on where my thinking and assumptions are wrong.

    The documentation for -[NSSet containsObject:] says:

    Return Value — YES if anObject is present in the set, otherwise NO.

    The documentation for -[NSSet member:] says:

    Return Value — If the set contains an object equal to object (as determined by isEqual:) then that object (typically this will be object), otherwise nil.

    Jim
  • On Feb 19, 2011, at 5:17 PM, Michael Crawford wrote:
    > When I look inside the set, you will see that the value -1748299021286640132 is in the set.  However, when -containsObject is called, it returns NO.

    Are you sure the objects you are dealing with are always NSNumbers? If one of them is an NSString, containsObject: will fail.

    On Feb 19, 2011, at 5:28 PM, Scott Ribe wrote:
    > I'm pretty sure that, for instance, two calls to [NSNumber numberWithLongLong: 1] will produce two different objects, and though they may fall into the same hash bucket if the hash method uses the numeric value, they will still not be treated as the same object by -containsObject.

    That would strike me as very odd, since it would imply that the two instances aren't isEqual: to each other. (The containsObject: doc isn't explicit about whether it uses isEqual: to test for membership, but I assume so since member: does.)

    I just did a quick test and confirmed that you do get two different instances with the same hash, but they are in face isEqual: to each other and hence their presence in a set is detected, as I would expect.

        NSNumber *one = [NSNumber numberWithLongLong:1];
        NSNumber *another = [NSNumber numberWithLongLong:1];
        NSSet *set = [NSSet setWithObject:another];

        NSLog(@"+++ one %p, hash = %ld -- another %p, hash = %ld -- is eq = %d, contains one = %d, contains another = %d",
              one, [one hash], another, [another hash], [one isEqual:another], [set containsObject:one], [set containsObject:another]);

    --Andy
  • On Feb 19, 2011, at 4:17 PM, Michael Crawford wrote:

    > I also assumed that whether or not the value is signed or unsigned; negative or positive makes no difference as long as calling the same accessor method on both NSNumber instances returns the same result.

    I think this is wrong.  I can't imagine why you assumed that some future method call would affect whether two NSNumbers are equal.  They are equal if they contain the same value.  You must realize that, for example, -boolValue would map a great many different NSNumbers to the same return value, but that doesn't imply that the NSNumbers are equal.

    Regards,
    Ken
  • On Feb 19, 2011, at 9:31 PM, Ken Thomases wrote:

    > On Feb 19, 2011, at 4:17 PM, Michael Crawford wrote:
    >
    >> I also assumed that whether or not the value is signed or unsigned; negative or positive makes no difference as long as calling the same accessor method on both NSNumber instances returns the same result.
    >
    > I think this is wrong.  I can't imagine why you assumed that some future method call would affect whether two NSNumbers are equal.  They are equal if they contain the same value.  You must realize that, for example, -boolValue would map a great many different NSNumbers to the same return value, but that doesn't imply that the NSNumbers are equal.
    >
    > Regards,
    > Ken
    >

    I assumed this is the case because regardless of whether or not you call -boolValue or -longLongValue, -hash returns the same result.  I've already shown that they do indeed contain the same value, when -longLongValue is called on both items.  See the dbg output.

    -Michael
  • On Feb 19, 2011, at 7:01 PM, Michael Crawford <michaelacrawford...> wrote:

    >
    > I assumed this is the case because regardless of whether or not you call -boolValue or -longLongValue, -hash returns the same result.  I've already shown that they do indeed contain the same value, when -longLongValue is called on both items.  See the dbg output.

    Why do you keep fixating on -hash? There are two common definitions of equality: -isEqual: and pointer identity. Neither of these relies on -hash.

    Your experience indicates that -containsObject: uses pointer identity, whereas -member: uses -isEqual:.

    --Kyle Sluder
    >
  • On Feb 19, 2011, at 6:08 PM, Andy Lee wrote:
    > I just did a quick test and confirmed that you do get two different instances with the same hash, but they are in face isEqual: to each other and hence their presence in a set is detected, as I would expect.
    >
    > NSNumber *one = [NSNumber numberWithLongLong:1];
    > NSNumber *another = [NSNumber numberWithLongLong:1];
    > NSSet *set = [NSSet setWithObject:another];
    >
    > NSLog(@"+++ one %p, hash = %ld -- another %p, hash = %ld -- is eq = %d, contains one = %d, contains another = %d",
    > one, [one hash], another, [another hash], [one isEqual:another], [set containsObject:one], [set containsObject:another]);

    Whoops, actually I got the same instance using 1, presumably because NSNumber keeps a few low number instances cached. What I said above is true if I retry with 123456789.

    --Andy
  • On Feb 19, 2011, at 9:01 PM, Michael Crawford wrote:

    > On Feb 19, 2011, at 9:31 PM, Ken Thomases wrote:
    >
    >> On Feb 19, 2011, at 4:17 PM, Michael Crawford wrote:
    >>
    >>> I also assumed that whether or not the value is signed or unsigned; negative or positive makes no difference as long as calling the same accessor method on both NSNumber instances returns the same result.
    >>
    >> I think this is wrong.  I can't imagine why you assumed that some future method call would affect whether two NSNumbers are equal.  They are equal if they contain the same value.  You must realize that, for example, -boolValue would map a great many different NSNumbers to the same return value, but that doesn't imply that the NSNumbers are equal.
    >
    > I assumed this is the case because regardless of whether or not you call -boolValue or -longLongValue, -hash returns the same result.

    So?  -hash being the same does not imply equality.  Equality implies that the hash must be the same, which is not the same thing.

    > I've already shown that they do indeed contain the same value, when -longLongValue is called on both items.  See the dbg output.

    And my point is exactly that this doesn't imply equality of the NSNumber objects.  Why would you think it does?  That's exactly like saying that calling -boolValue on both items gave the same result so therefore they must be equal.

    Notice that when the description is printed, you got 16698445052422911484 from [mediaItem persistentIDProperty] while the elements of the set show -1748299021286641066, -1748299021286641065, and -1748299021286640132.  That's an indication that the numbers are not the same "under the hood".  At the very least, one is positive while the others are negative.

    You are essentially asking NSNumber whether the numbers 16698445052422911484 and -1748299021286640132 are equal, and it's giving you the fairly obvious answer that, no, they are different numbers.  Yes, when cast to long long, they both end up as the same long long value, but that's a transformation that throws away information about the original numbers.  It doesn't mean the original numbers are equal.

    Regards,
    Ken
  • On Feb 19, 2011, at 19:06, Kyle Sluder wrote:

    > On Feb 19, 2011, at 7:01 PM, Michael Crawford <michaelacrawford...> wrote:
    >
    >>
    >> I assumed this is the case because regardless of whether or not you call -boolValue or -longLongValue, -hash returns the same result.  I've already shown that they do indeed contain the same value, when -longLongValue is called on both items.  See the dbg output.
    >
    > Why do you keep fixating on -hash? There are two common definitions of equality: -isEqual: and pointer identity. Neither of these relies on -hash.

    Putting it another way: -hash is of interest only to *implementers* of certain classes. To users of classes, it's an implementation detail.

    > Your experience indicates that -containsObject: uses pointer identity, whereas -member: uses -isEqual:.

    What's especially confusing is that -[NSArray containsObject:] is documented to use -isEqual. It seems like the NSSet method ought to be called -containsObjectIdenticalTo: for consistency (and now clarity) reasons.
  • On Feb 19, 2011, at 9:26 PM, Quincey Morris wrote:

    > On Feb 19, 2011, at 19:06, Kyle Sluder wrote:
    >
    >> Your experience indicates that -containsObject: uses pointer identity, whereas -member: uses -isEqual:.
    >
    > What's especially confusing is that -[NSArray containsObject:] is documented to use -isEqual. It seems like the NSSet method ought to be called -containsObjectIdenticalTo: for consistency (and now clarity) reasons.

    I think Kyle was just mistaken about this, lead astray by Michael's claims.  Andy's experiment shows that -[NSSet containsObject:] relies on equality, not identity, just as one expects.  It's just that Michael has two truly non-equal NSNumber objects, as his gdb output showed.

    Regards,
    Ken
  • On Feb 19, 2011, at 10:31 PM, Ken Thomases wrote:

    > On Feb 19, 2011, at 9:26 PM, Quincey Morris wrote:
    >
    >> On Feb 19, 2011, at 19:06, Kyle Sluder wrote:
    >>
    >>> Your experience indicates that -containsObject: uses pointer identity, whereas -member: uses -isEqual:.
    >>
    >> What's especially confusing is that -[NSArray containsObject:] is documented to use -isEqual. It seems like the NSSet method ought to be called -containsObjectIdenticalTo: for consistency (and now clarity) reasons.
    >
    > I think Kyle was just mistaken about this, lead astray by Michael's claims.  Andy's experiment shows that -[NSSet containsObject:] relies on equality, not identity, just as one expects.  It's just that Michael has two truly non-equal NSNumber objects, as his gdb output showed.

    BTW I was technically mistaken about my code's output. You get the *same* instance when you do [NSNumber numberWithLongLong:1] twice, because NSNumber happens to cache instances for low integer values. But I was correct in principle: substitute 123456789 for 1 and everything I said becomes true.

    One thing I'm puzzled about is that NSSet does not copy its entries the way NSDictionary copies its keys. This is implied by the member: documentation quoted earlier:

    "If the set contains an object equal to object (as determined by isEqual:) then that object (***typically this will be object***), otherwise nil."

    A quick experiment confirms that elements are not copied, which leads to the risk that NSDictionary avoids. If elements of the set happen to be mutable, one element could mutate in such a way as to be isEqual: to another. This can be demonstrated actually happening:

    NSMutableString *s1 = [NSMutableString stringWithString:@"abc"];
    NSMutableString *s2 = [NSMutableString stringWithString:@"abc"];
    NSMutableString *s3 = [NSMutableString stringWithString:@"def"];
    NSSet *stringSet = [NSSet setWithObjects:s1, s2, s3, nil];

    NSLog(@"+++ s1 [%@] %p, hash = %ld, set contains s1? %d", s1, s1, [s1 hash], [stringSet containsObject:s1]);
    NSLog(@"+++ s2 [%@] %p, hash = %ld, set contains s2? %d", s2, s2, [s2 hash], [stringSet containsObject:s2]);
    NSLog(@"+++ s3 [%@] %p, hash = %ld, set contains s3? %d", s3, s3, [s3 hash], [stringSet containsObject:s3]);

    NSLog(@"+++ elements BEFORE mutate:");
    for (id obj in stringSet)
    {
      NSLog(@"+++    %p is [%@]", obj, obj);
    }

    [s3 setString:@"abc"];  // Mutate one set element to be equal to another.

    NSLog(@"+++ count after mutate = %d", [stringSet count]);
    NSLog(@"+++ elements AFTER mutate:");
    for (id obj in stringSet)
    {
      NSLog(@"+++    %p is [%@] -- is eq to @\"abc\"? %d", obj, obj, [obj isEqual:@"abc"]);
    }

    Output:

    2011-02-20 00:47:19.305 Scratcho[20333:a0f] +++ s1 [abc] 0x12b170, hash = 516202353, set contains s1? 1
    2011-02-20 00:47:19.309 Scratcho[20333:a0f] +++ s2 [abc] 0x12b1b0, hash = 516202353, set contains s2? 1
    2011-02-20 00:47:19.310 Scratcho[20333:a0f] +++ s3 [def] 0x12b1f0, hash = 517992642, set contains s3? 1
    2011-02-20 00:47:19.310 Scratcho[20333:a0f] +++ elements BEFORE mutate:
    2011-02-20 00:47:19.311 Scratcho[20333:a0f] +++    0x12b170 is [abc]
    2011-02-20 00:47:19.313 Scratcho[20333:a0f] +++    0x12b1f0 is [def]
    2011-02-20 00:47:19.313 Scratcho[20333:a0f] +++ count after mutate = 2
    2011-02-20 00:47:19.314 Scratcho[20333:a0f] +++ elements AFTER mutate:
    2011-02-20 00:47:19.315 Scratcho[20333:a0f] +++    0x12b170 is [abc] -- is eq to @"abc"? 1
    2011-02-20 00:47:19.315 Scratcho[20333:a0f] +++    0x12b1f0 is [abc] -- is eq to @"abc"? 1

    Am I missing something? Is this a known loophole in the semantics of NSSet? Is it a deliberate compromise, which trades the performance gained by not copying elements for a risk that almost never matters in practice?

    --Andy
  • On 20-Feb-2011, at 1:54 PM, Andy Lee wrote:

    >
    > One thing I'm puzzled about is that NSSet does not copy its entries the way NSDictionary copies its keys. This is implied by the member: documentation quoted earlier:
    >
    > "If the set contains an object equal to object (as determined by isEqual:) then that object (***typically this will be object***), otherwise nil."
    >
    > A quick experiment confirms that elements are not copied, which leads to the risk that NSDictionary avoids. If elements of the set happen to be mutable, one element could mutate in such a way as to be isEqual: to another. This can be demonstrated actually happening:
    >

    No experiment needed - it's in the documentation .. quoting ..

    "The objects in a set must respond to the NSObject protocol methods hash and isEqual: (see NSObject for more information). If mutable objects are stored in a set, either the hash method of the objects shouldn’t depend on the internal state of the mutable objects or the mutable objects shouldn’t be modified while they’re in the set. For example, a mutable dictionary can be put in a set, but you must not change it while it is in there. (Note that it can be difficult to know whether or not a given object is in a collection)."
    "NSSet provides a number of initializer methods, such as setWithObjects: and initWithArray:, that return an NSSet object containing the elements (if any) you pass in as arguments. Objects added to a set are not copied (unless you pass YES as the argument to initWithSet:copyItems:). Rather, an object is added directly to a set. In a managed memory environment, an object receives a retain message when it’s added; in a garbage collected environment, it is strongly referenced. For more information on copying and memory management, see “Copying Collections.”"
  • Ah, thanks. That's here:

    <http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Coll
    ections/Articles/Sets.html
    >

    I was only looking at the NSSet docs.

    --Andy

    On Feb 20, 2011, at 1:03 AM, Roland King wrote:

    >
    > On 20-Feb-2011, at 1:54 PM, Andy Lee wrote:
    >
    >>
    >> One thing I'm puzzled about is that NSSet does not copy its entries the way NSDictionary copies its keys. This is implied by the member: documentation quoted earlier:
    >>
    >> "If the set contains an object equal to object (as determined by isEqual:) then that object (***typically this will be object***), otherwise nil."
    >>
    >> A quick experiment confirms that elements are not copied, which leads to the risk that NSDictionary avoids. If elements of the set happen to be mutable, one element could mutate in such a way as to be isEqual: to another. This can be demonstrated actually happening:
    >>
    >
    > No experiment needed - it's in the documentation .. quoting ..
    >
    > "The objects in a set must respond to the NSObject protocol methods hash and isEqual: (see NSObject for more information). If mutable objects are stored in a set, either the hash method of the objects shouldn’t depend on the internal state of the mutable objects or the mutable objects shouldn’t be modified while they’re in the set. For example, a mutable dictionary can be put in a set, but you must not change it while it is in there. (Note that it can be difficult to know whether or not a given object is in a collection)."
    > "NSSet provides a number of initializer methods, such as setWithObjects: and initWithArray:, that return an NSSet object containing the elements (if any) you pass in as arguments. Objects added to a set are not copied (unless you pass YES as the argument to initWithSet:copyItems:). Rather, an object is added directly to a set. In a managed memory environment, an object receives a retain message when it’s added; in a garbage collected environment, it is strongly referenced. For more information on copying and memory management, see “Copying Collections.”"
    >
  • Michael Crawford wrote:

    > The following gdb console output demonstrates an instance of a
    > media-item persistent-ID property that, when queried gives a large
    > unsigned number.  When I ask again using the -longLongValue method,
    > I get the answer I was expecting.  When I look inside the set, you
    > will see that the value -1748299021286640132 is in the set.
    > However, when -containsObject is called, it returns NO.

    If the persistent-ID is unsigned, then longLongValue seems like the
    wrong type to use.  There are NSNumber methods for working with
    unsigned long long types.  Try using those exclusively and see if it
    changes anything.

    NSNumber has a method that returns the type encoding as a C string (-
    objCType).  The long long type has a different value from the
    unsigned long long type: "q" vs. "Q".

    There's also this special consideration (see NSNumber class reference
    doc):
    "The returned type does not necessarily match the method the receiver
    was created with."

    http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/
    Foundation/Classes/NSNumber_Class/Reference/Reference.html%23//
    apple_ref/occ/cl/NSNumber

    The type encodings reference:
    http://developer.apple.com/library/mac/#documentation/Cocoa/
    Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html%23//
    apple_ref/doc/uid/TP40008048-CH100-SW1

    If nothing else works, convert the persistent-ID number to NSString,
    using an encoding like BASE64 or simply hex in a consistent upper or
    lower case.  I doubt that the performance cost for a string would be
    so high that making your own NSValue subclass would be worthwhile.

      -- GG
  • On Sat, 19 Feb 2011 17:17:36 -0500, Michael Crawford <michaelacrawford...> said:
    > I'm trying to compare instances of NSNumber using NSSet.  I have a set of numbers, which represent 64-bit persistent IDs for iTunes media-items.  I access these values using the -[NSNumber longLongValue] method.

    You're having a fundamental numerics mismatch. The problem is that the 64-bit persistent IDs for iTunes media items are not long long, so reading them with longLongValue will give you the wrong answer. They are *unsigned* long long, which is a different animal.

    This matter has been discussed fairly extensively on StackOverflow. My own preference for reading these items is to leave them as NSNumber wherever possible; if I need an alternative representation, I pass them through @"%@" as a string format, which results in a string that does the right thing. See also:

    http://stackoverflow.com/questions/1181637/storing-and-retrieving-unsigned-
    long-long-value-to-from-nsstring


    m.

    --
    matt neuburg, phd = <matt...>, <http://www.apeth.net/matt/>
    A fool + a tool + an autorelease pool = cool!
    AppleScript: the Definitive Guide - Second Edition!
    On 19 Feb 2011, at 2:17 PM, Michael Crawford wrote:
    > Anyone have previous experience with this problem?  Can you shed some light on where my thinking and assumptions are wrong.  I could write a sweet of tests to try and prove/disprove what I think is happening but I'm hoping to benefit from someone else's pre-existing research, experiments, or internal knowledge.

    One thing to check is to find two NSNumbers which you think should be equal, and see whether they return YES to -isEqual:. This is the form of equality which NSSet is interested in. (-hash is an optimization.)

    > I also assumed that whether or not the value is signed or unsigned; negative or positive makes no difference as long as calling the same accessor method on both NSNumber instances returns the same result.

    I think this is the false assumption that is giving you grief. Calling an accessor whose return type can't represent the NSNumber's value will return a value which has been converted according to C's casting rules (as far as I know). Consider two large numbers whose bottom 16 bits are the same; calling -unsignedShortValue on them will return the same value, but you wouldn't expect (or want) those numbers to compare equal.

    It looks like the contents of your noPlaySongs array were created using numberWithLongLong:. Is there a reason not to use numberWithUnsignedLongLong: to create them (as Greg Guerin suggests)? Or, ideally, never convert them to a C integer representation in the first place and treat them as if they were opaque objects (as Matt Neuburg suggests)? There's a fundamental difficulty, which is that there is no C type which can represent the values of all possible NSNumbers of integral types, (or even all C integers!), so roundtripping the number through a plain integer type is fraught with peril unless you know (or can figure out) which C type to use.

    (IIRC, there are still a few small warts in NSNumber/CFNumber's behavior which come from the fact that the numeric types implemented by CFNumber are not compatible with the numeric types implemented by NSNumber, and yet NSNumber is toll-free-bridged to CFNumber. I don't think this is related to your problem, though.)
  • Creating the NSNumber objects using unsignedLongLong instead of longLong solved my problem.  Thanks to everyone who participated in the lively discussion.

    Sorry for being a little slow in closing the loop.

    -Michael

    On Feb 21, 2011, at 9:50 PM, Wim Lewis wrote:

    >
    > On 19 Feb 2011, at 2:17 PM, Michael Crawford wrote:
    >> Anyone have previous experience with this problem?  Can you shed some light on where my thinking and assumptions are wrong.  I could write a sweet of tests to try and prove/disprove what I think is happening but I'm hoping to benefit from someone else's pre-existing research, experiments, or internal knowledge.
    >
    > One thing to check is to find two NSNumbers which you think should be equal, and see whether they return YES to -isEqual:. This is the form of equality which NSSet is interested in. (-hash is an optimization.)
    >
    >> I also assumed that whether or not the value is signed or unsigned; negative or positive makes no difference as long as calling the same accessor method on both NSNumber instances returns the same result.
    >
    > I think this is the false assumption that is giving you grief. Calling an accessor whose return type can't represent the NSNumber's value will return a value which has been converted according to C's casting rules (as far as I know). Consider two large numbers whose bottom 16 bits are the same; calling -unsignedShortValue on them will return the same value, but you wouldn't expect (or want) those numbers to compare equal.
    >
    > It looks like the contents of your noPlaySongs array were created using numberWithLongLong:. Is there a reason not to use numberWithUnsignedLongLong: to create them (as Greg Guerin suggests)? Or, ideally, never convert them to a C integer representation in the first place and treat them as if they were opaque objects (as Matt Neuburg suggests)? There's a fundamental difficulty, which is that there is no C type which can represent the values of all possible NSNumbers of integral types, (or even all C integers!), so roundtripping the number through a plain integer type is fraught with peril unless you know (or can figure out) which C type to use.
    >
    >
    > (IIRC, there are still a few small warts in NSNumber/CFNumber's behavior which come from the fact that the numeric types implemented by CFNumber are not compatible with the numeric types implemented by NSNumber, and yet NSNumber is toll-free-bridged to CFNumber. I don't think this is related to your problem, though.)
    >
    >
previous month february 2011 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28            
Go to today