Date
1 - 10 of 10
Difference between NSPoint, NSSize, NSRect and the CG Versions
Dave
Hi,
Is there any real difference between NSPoint, NSRect, NSSize etc. and the CG versions? I can use the CG Versions on Mac and iOS but the NS versions only on Mac. If I only used the CG versions it would compile ok for both platforms, but is this wise, or is it best to use NS on Mac? All the Best Dave |
|
Alex Zavatone
Look at the types that back them.
toggle quoted message
Show quoted text
Structs and CGFloats? On Aug 31, 2017, at 6:03 AM, Dave <dave@...> wrote: |
|
Dave
Well,
toggle quoted message
Show quoted text
typedef CGRect NSRect; So, it looks like they are one and the same thing? But in that case why are there two sets? I’m just trying to understand what these different types are supposed to be used for. Cheers Dave On 31 Aug 2017, at 13:05, Alex Zavatone <zav@...> wrote: |
|
Historical reasons. AppKit predates Core Graphics (it predates Apple's acquisition of NeXT.) —Jens |
|
Quincey Morris
On Aug 31, 2017, at 04:12 , Dave <dave@...> wrote:
There are “really” four different SDKs: — 32-bit macOS — 64-bit macOS — 32-bit iOS — 64-bit iOS They are different in the sense that certain basic C types (such as int and float) are potentially different byte sizes, and certain derived Obj-C types (such as CGFloat, NSInteger and NSUInteger) are based on different C types (which may or may not affect their size). In all SDKs other than 32-bit macOS, the NS and CG variants of points, rects, etc are synonyms, and can be used interchangeably. In the 32-bit macOS SDK, they are based on different underlying types. Even if the struct members are the same size (they are, IIRC, all 4 bytes), the difference in type means the NS and CG versions are not technically compatible at the ABI level — at the calling interface between functions, for example. Somewhere around macOS 10.5, when 64-bit macOS was introduced, it also became possible to compile 32-bit apps with a “compile like 64-bit” setting, which brought the 32-bit SDK in line with all the rest, and made the NS and CG types compatible. However, you had to opt into that manually, because using that option would make your code ABI-incompatible with (say) existing 3rd party frameworks that didn’t use the option. In short, there are two sets (as Jens said) for historical reasons. Apple seems to have settled on the CG versions as the new normal, so you should always use those in new code, except in the rare case where you’re writing an app that needs to deployable on old 32-bit only Macs. IIRC, Macs running 10.6.8 or higher have full 64-bit support, and again IIRC current macOS versions don’t support 32-bit code at all. |
|
I don't see how they could be incompatible if they're the same size. The only 4-byte floating point type is 'float', so if the CG and NS types are using the same-size values, how can they be different underlying types? (I don't remember the details, but perhaps in 32-bit the NS types used float while the CG types used double?) —Jens |
|
Quincey Morris
On Aug 31, 2017, at 12:19 , Jens Alfke <jens@...> wrote:
I don’t remember the exact details either, but one issue is that there are places in the Obj-C runtime/metadata/whatever where the @encode string of a method signature matters, and some similar same-size, same-representation types are represented by different letters in the string. This could mean that although method parameters and return values were bit-for-bit identical, the type encoding made the methods incompatible. One particular example I remember, unrelated to this thread’s topic, is that in 64-bit, NSUInteger encoded to “Q” (quad-word, i.e. long long) not “L” (long). Both types were 8 bytes, and NSUInteger was even typedef’ed to long (IIRC), but “L” was never used in that architecture. The NSPoint/CGPoint thing was something like that. IIRC, NSPoint used float, and CGPoint used CGFloat, and those @encoded differently for some reason. |
|
Steve Christensen <punster@...>
Here are the definitions copied from my iOS SDK headers. The types/sizes for CGFloat and NS[U]Integer track the 32-/64-bit architecture used to build a particular executable. typedef CGFLOAT_TYPE CGFloat; #if defined(__LP64__) && __LP64__ # define CGFLOAT_TYPE double #else # define CGFLOAT_TYPE float #endif #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 Regarding NSPoint, I see it defined as typedef CGPoint NSPoint; so its x and y fields will be CGFloats.
|
|
Quincey Morris
On Aug 31, 2017, at 14:07 , Steve Christensen <punster@...> wrote:
Opening up a macOS project and looking at the definition of NSPoint, I see:
So, it was the same size as CGPoint, but a different struct name, which was enough to create an ABI incompatibility. You could opt into the new typedef for 32-bit by using NS_BUILD_32_LIKE_64. |
|
Dave
Thanks a lot Quincey and Jens for your through explanation - I had imported some Mac code from another project which uses NSRect’s and as my original project was iOS this caused compile errors, so rather than trying to handle both sets, I’ll just use the CG versions from now on.
toggle quoted message
Show quoted text
There are a few calls to NSInsetRect, NSOffsetRect, etc., too, I’m guessing these can just be replaced with the CG version too. Thanks again All the Best Dave
|
|