Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When moving to Mac from iOS in Objective-C development, NSIntegers give type matching errors

I've been working on an iOS project for some time now, and I've recently decided to port the code to a Mac project. Because I've chosen to use NSInteger in my code, and NSInteger is a environment-dependent typecast, it means that my variables are different types on the iOS and Mac apps.

When I run the test suite on the Mac, all my STAssertEquals calls fail with the error "Type mismatch --" because the types don't match:

NSInteger foo = 1;
STAssertEquals(foo, 1, nil); // Test fails!!

Typecasting my scalars seems to work, but this seems really messy:

NSInteger foo = 1;
STAssertEquals(foo, (NSInteger)1, nil); // Succeeds, but is ugly!!

Am I missing something here? I'm starting to suspect that the decision to use NSIntegers was a poor choice.

Update: Perhaps this article is related. It seems to support typecasting scalars.

like image 716
Brent Traut Avatar asked Feb 01 '12 03:02

Brent Traut


1 Answers

Your use of NSInteger is probably the right choice, but it does cause some issues with STAssertEquals.

STAssertEquals fails if the two objects have different Objective-C type encodings

A lone 1 will be interpreted by the C compiler as a (signed int), which has type encoding "i".

These macros would also fail:

unsigned u = 1;
STAssertEquals(u, 1, nil); // Fails because u is type "I" (unsigned int) and 1 is type "i" (int)

char c = 1;
STAssertEquals(c, 1, nil); // Fails because c is type "c" (signed char) and 1 is type "i" (signed int)

To make the compiler use a different type for 1, you would add a suffix such as 1U for (unsigned int), 1UL for (unsigned long) or 1L for (long).

NSInteger is defined to be the same size as pointers, which is dependent on the device architecture. On 32-bit Mac OS X and iOS, NSInteger is type (signed int), or "i". On 64-bit Mac OS X, it is type long, or "q". (64-bit Mac OS X is a LP64 architecture, which means that Longs and Pointers are both 64-bits wide)

Thus, the left side of your STAssertEquals is a "q", whereas the right side is "i", causing the type mismatch.

Your solution of using (NSInteger) 1 seems to accurately represent what you want - test an NSInteger variable against an NSInteger constant of value 1.

like image 93
iccir Avatar answered Nov 15 '22 07:11

iccir