3

My intention is to compare CGPoints or CGPoint values (and as the app is also for Mac OS NSPoints or NSPoint values) of several moving objects to detect if the objects have the same position.

My first solution to this was to fast enumerate an array of those objects and store all CGPoints to an array, then fast enumerate the array of objects again to check whether the position is the same of any other object:

// STEP 1: Collect all Positions
NSMutableArray *allPositions = [NSMutableArray arrayWithCapacity:self.allObjects.count];
for (Object *myObject in self.allObjects) {
    CGPoint myObjectPosition = ...;
    [allPositions addObject:myObjectPosition]; // Problem here
}

// STEP 2: Check for Overlapping
for (Object *myObject in self.allObjects) {
    CGPoint myObjectPosition = ...;
    if ([allPositions containsObject:myObjectPosition] {
        // Overlapping
    }
}

The problem with this is adding the points to the allPositions Array. Therefore NSValue can be used:

[NSValue valueWithCGPoint:point];

But this does work only under iOS, for Mac OS there has to be used valueWithPoint and NSPoint.

Can I save maybe save the x and the y values in dictionaries and store them to the allPositions Array? Or is there an even better solution without having 2x fast enumerations? There are about 100 objects in self.allObjects...

Sezgin
  • 239
  • 1
  • 2
  • 9
FrankZp
  • 2,022
  • 3
  • 28
  • 41

3 Answers3

6

CGPoint and NSPoint are the same struct. It doesn't matter if they got a different name, they both hold two CGFloat. They got the same size and the same alignment, and therefore they can be used interchangeably. So in your case valueWithPoint: fits.

Edit

About the second thing you ask, this should be done with macros:

#if TARGET_OS_IPHONE
    value= [NSValue valueWithCGPoint: point];
#else 
    value= [NSValue valueWithPoint: point];
#endif

Getting the point back:

#if TARGET_OS_IPHONE
    point= value.CGPointValue;
#else
    point= value.pointValue;
#endif

http://sealiesoftware.com/blog/archive/2010/8/16/TargetConditionalsh.html

Ramy Al Zuhouri
  • 21,580
  • 26
  • 105
  • 187
  • The code should be valid for iOS and Mac OS. `valueWithPoint` will only work if the target is Mac OS. Building with an iOS target leads to an error `No known class method for 'valueWithPoint:'`... – FrankZp Jun 18 '13 at 13:00
  • You solve this using a macro to execute conditional code, according to the platform (see the edit). – Ramy Al Zuhouri Jun 18 '13 at 13:20
  • ok but then when converting back a typecast is still needed for one platform (see comment by Parag Bafna). Can you please update your code for converting the NSValues back to points? – FrankZp Jun 18 '13 at 13:24
  • I added the code to get the point back, but you don't need a cast, they're the same type. Like Bafna pointed out it's : typedef CGPoint NSPoint;". Try it, you'll get no errors nor warnings. – Ramy Al Zuhouri Jun 18 '13 at 15:31
1

While working on universal iOS/OSX app i solved this problem by using NSValue category. NSValue+CGPoint.h:

@interface NSValue (CGPoint)
#if TARGET_OS_MAC
+ (NSValue *)valueWithCGPoint:(CGPoint)point;
- (CGPoint)CGPointValue;
#endif
@end

NSValue+CGPoint.m:

#import "NSValue+CGPoint.h"
@implementation NSValue (CGPoint)
#if TARGET_OS_MAC
+ (NSValue *)valueWithCGPoint:(CGPoint)point {
    return [NSValue valueWithPoint:point];
}

- (CGPoint)CGPointValue {
    return [self pointValue];
}
#endif
@end

Now i can use the same code on both iOS and Mac, for example:

// store point in NSValue
CGPoint p = {10, 10};
NSValue *v = [NSValue valueWithCGPoint:p];

// read point from NSValue
CGPoint p2 = [v CGPointValue];
Slyv
  • 421
  • 3
  • 8
0
//NSGeometry.h  
  typedef CGPoint NSPoint;

//CGGeometry.h
struct CGPoint {
  CGFloat x;
  CGFloat y;
};
typedef struct CGPoint CGPoint;

NSPoint and CGpoint are same;

// NSValue/+valueWithPoint:(NSPoint)point is available on Mac OS X
// NSValue/+valueWithCGPoint:(CGPoint)point is available on iOS


//save value in CGPoint

if([NSValue respondsToSelector:@selector(valueWithPoint:)])
{
    NSPoint lPoint = NSPointFromCGPoint(lCGPoint);
    // do some op
}
else {
    // do some op
}

EDIT

Dont use respondsToSelector, use TARGET_OS_IPHONE macro.

Parag Bafna
  • 22,812
  • 8
  • 71
  • 144
  • I know that they both hold `CGFloat x, y`. But if you look at several class references you'll notice that Mac OS methods only work with NSPoint and iOS methods only work with CGPoint. I have no idea how to get a universal solution... – FrankZp Jun 18 '13 at 13:06
  • 1
    You can type cast.use NSPointFromCGPoint – Parag Bafna Jun 18 '13 at 13:14
  • is it also possible the other way? NSPoint -> CGPoint? – FrankZp Jun 18 '13 at 13:25
  • With the macro *TARGET_OS_IPHONE* you know at compile time on what platform you are. Doing this choice at runtime is wrong and a wastage of resources. – Ramy Al Zuhouri Jun 18 '13 at 15:46