16

How do you encode and decode a CGPoint struct using NSCoder?

Paulo Mattos
  • 18,845
  • 10
  • 77
  • 85
mikechambers
  • 3,047
  • 3
  • 24
  • 31
  • Just leaving this here for others. In Swift on MacOSX CGPoint is the same as NSPoint: public func encodeWithCoder(coder: NSCoder) { coder.encodePoint(myNSPoint, forKey: "someKeyName") } – Jubei Mar 09 '16 at 12:42

3 Answers3

26

To encode:

CGPoint point = /* point from somewhere */
NSValue *pointValue = [NSValue value:&point withObjCType:@encode(CGPoint)];
[coder encodeObject:pointValue forKey:@"point"];

To decode:

NSValue *decodedValue = [decoder decodeObjectForKey:@"point"];
CGPoint point;
[decodedValue getValue:&point];
sbooth
  • 16,646
  • 2
  • 55
  • 81
17

Just an update for iOS developers. You can do the following in Cocoa Touch (but not in Cocoa):

[coder encodeCGPoint:myPoint forKey:@"myPoint"];
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Eric G
  • 1,429
  • 18
  • 26
10

CGPoints and NSPoints are both structures composed of two CGFloat values, so you can freely pass them around as each other. The quick and dirty way would be:

NSCoder *myNSCoder;
CGPoint myPoint;
[myNSCoder encodePoint:*(NSPoint *)myPoint];

This will usually work, but it technically breaks the C99 strict aliasing rules. If you want to be 100% compatible with the standard, you'll have to do something like:

typedef union
{
  CGPoint cgPoint;
  NSPoint nsPoint;
} CGNSPoint;

CGNSPoint cgnsPoint = { .cgPoint = myPoint };
[myNSCoder encodePoint:cgnsPoint.nsPoint];
Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • 2
    However, if you’re building for the 64-bit runtime, or have NS_BUILD_32_LIKE_64 defined to 1, NSPoint and CGPoint are typedefed to the same struct, so no casting or union shenanigans are required. – Jens Ayton Jan 15 '09 at 20:55
  • 3
    Furthermore, Foundation provides two inline functions named NSPoint{To,From}CGPoint. No need for pointer casting or a union. – Peter Hosey Jan 16 '09 at 02:30