Can't withdraw CGPoint Values from A mutableArray of NSValue - objective-c

I made an NSMUtableArray of CGpoints and I stored them by subclassing as NSValue, but I cant get the values out. here I what I did.
CGPoint graphPoint;
NSMutableArray *pointValues = [[NSMutableArray alloc] init];
for( int x =0;x<5; x++)
{
NSDictionary* xValue = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:x] forKey:#"X"];
graphPoint.x =x;
graphPoint.y = [CalculatorBrain runProgram: self.graphingPoint usingVariableValues:xValue];
[pointValues addObject:[NSValue valueWithCGPoint:graphPoint]];
}
I tried using this to get the values but I just get null back
for( int x=0; x<5; x++) {
NSValue *val = [pointValues objectAtIndex:x];
CGPoint point = [val CGpointValue];
NSLog(#"Points = %#", point);
}

You can't print a CGPoint using the %# format specifier, as it is not an object. Instead, use NSStringFromCGPoint():
NSLog(#"%#", NSStringFromCGPoint(myPoint));

Related

Plot Points from dictionary

I'm getting latitude, longitude and many other fields from the server.
I put each row from the database in a separate dictionary within a array.
I'm trying to map out a point from the latitude and longitude, but when I try to access the latitude by key I get a compiler error No visible #interface for NSDictionary....
Server Response
[{"id":1,"user_id":0,"latitude":"42.2367","longitude":"-71.11332","status":"active","responded_at":null,"created_at":"2015-04-13T12:52:51.144Z","updated_at":"2015-04-13T12:52:51.161Z"},{"id":2,"user_id":0,"latitude":"42.23497","longitude":"-71.11238","status":"active","responded_at":null,"created_at":"2015-04-13T12:57:03.000Z","updated_at":"2015-04-13T12:57:03.002Z"},{"id":3,"user_id":0,"latitude":"42.24222","longitude":"-71.11536","status":"active","responded_at":null,"created_at":"2015-04-13T12:57:49.012Z","updated_at":"2015-04-13T12:57:49.014Z"},{"id":4,"user_id":0,"latitude":"42.24194","longitude":"-71.11556","status":"active","responded_at":null,"created_at":"2015-04-13T13:03:10.710Z","updated_at":"2015-04-13T13:03:10.713Z"},{"id":5,"user_id":0,"latitude":"42.23493","longitude":"-71.11244","status":"active","responded_at":null,"created_at":"2015-04-13T13:05:39.713Z","updated_at":"2015-04-13T13:05:39.716Z"},{"id":6,"user_id":0,"latitude":"42.23598","longitude":"-71.11467","status":"active","responded_at":null,"created_at":"2015-04-13T13:08:12.983Z","updated_at":"2015-04-13T13:08:12.986Z"},{"id":7,"user_id":0,"latitude":"42.23598","longitude":"-71.11467","status":"active","responded_at":null,"created_at":"2015-04-13T13:08:38.115Z","updated_at":"2015-04-13T13:08:38.118Z"},{"id":8,"user_id":0,"latitude":"42.23794","longitude":"-71.11471","status":"active","responded_at":null,"created_at":"2015-04-13T13:10:11.593Z","updated_at":"2015-04-13T13:11:19.467Z"}]
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// The request is complete and data has been received
// You can parse the stuff in your instance variable now
NSError *error;
NSMutableDictionary *json = [NSJSONSerialization
JSONObjectWithData:_responseData
options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves
error:&error];
for (int i = 0; i < json.count; i++) {
double latitude = [[json objectAtIndex:i] objectForKey:#"latitude"];
double longitude = [[[json objectForKey:#"longitude"]objectAtIndex:i] doubleValue];
CLLocationCoordinate2D latlng = CLLocationCoordinate2DMake(latitude, longitude);
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
[point setCoordinate:latlng];
[worldView addAnnotation:point];
}
}
The server response (like you say in the question) is an array of dictionaries.
So json should be declared as an NSArray not an NSMutableDictionary.
This is what causes the compiler error No visible #interface for NSDictionary... because NSMutableDictionary does not have a objectAtIndex: method.
In addition, the code to get the longitude is backwards (it treats json like a dictionary and then tries to access an array inside the resulting key value).
The corrected code would be:
NSArray *json = [NSJSONSerialization
JSONObjectWithData:_responseData
options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves
error:&error];
for (int i = 0; i < json.count; i++) {
NSDictionary *pointDictionary = [json objectAtIndex:i];
double latitude = [[pointDictionary objectForKey:#"latitude"] doubleValue];
double longitude = [[pointDictionary objectForKey:#"longitude"] doubleValue];
CLLocationCoordinate2D latlng = CLLocationCoordinate2DMake(latitude, longitude);
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
[point setCoordinate:latlng];
[worldView addAnnotation:point];
}

Unable to replace object in NSMutableArray

Somehow the code below is throwing a NSInvalidArgumentException, although I followed step by step to make sure everything has proper value...
I have an array of CGPoints stored in NSValues, and this is part of a method to offset all points by (x,y).
for (int i = 0; i < [allPoints count]; i++) {
CGPoint pt = [[allPoints objectAtIndex:i] CGPointValue];
CGPoint newPt = CGPointMake(pt.x + x, pt.y + y);
NSValue *newEntry = [NSValue valueWithCGPoint:newPt];
[allPoints replaceObjectAtIndex:i withObject:newEntry];
}
try this ,
-----------------------------sample code---------------------------------
CGPoint pt =CGPointMake(20, 30);
NSValue *point = [NSValue valueWithCGPoint:pt];
CGPoint pt2 =CGPointMake(40, 40);
NSValue *point2 = [NSValue valueWithCGPoint:pt2];
NSMutableArray *allPoints =[[NSMutableArray alloc]initWithObjects:point,point2, nil];
NSLog(#"%#",allPoints);
// -------------output----------
// "NSPoint: {20, 30}",
// "NSPoint: {40, 40}"
int x=10; int y=20;
for (int i = 0; i < [allPoints count]; i++)
{
CGPoint pt = [[allPoints objectAtIndex:i] CGPointValue];
CGPoint newPt = CGPointMake(pt.x + x, pt.y + y);
NSValue *newEntry = [NSValue valueWithCGPoint:newPt];
[allPoints replaceObjectAtIndex:i withObject:newEntry];
}
NSLog(#"%#",allPoints);
// -------------output----------
// "NSPoint: {30, 50}",
// "NSPoint: {50, 60}"
NSMutableArray method replaceObjectAtIndex:withObject raises an NSInvalidArgumentException if object at given index is nil or new object is nil.
Double check if one of objects in allPoints NSMutableArray is nil.
Or allPoints NSMutableArray doesn't contain NSValue objects with CGPoint elements.
I do not know how, but it seems although I declared allPoints to be NSMutableArray and after a search in my entire code I cannot find in any place where I set the pointer of allPoints to a NSArray, but the system seems to think now that allPoints is now a NSArray and hence I cannot replace any objects.
Therefore I have to circumvent with a new NSMutableArray.
for (int i = 0; i < [allPoints count]; i++) {
CGPoint pt = [[allPoints objectAtIndex:i] CGPointValue];
CGPoint newPt = CGPointMake(pt.x + x, pt.y + y);
NSValue *newEntry = [NSValue valueWithCGPoint:newPt];
NSMutableArray *temp = [NSMutableArray arrayWithArray:allPoints];
[temp replaceObjectAtIndex:i withObject:newEntry];
allPoints = temp;
}

Cannot Position Instance of Subclass of CCSprite

I'm not terribly new to Objective-C, but I can't figure out this issue. I'm attempting to create an instance of a subclass of CCSprite that I made, but it always creates the instance at (0,0), and I can't move it. I've set up my code so that it parses a .txt file in which I put level information, and then it creates sprites based on that information.
Here's the code that initializes the sprite:
-(void)initLevel{
NSLog(#"Level %i is of length %i", lvlNum, [FileReader getLengthOfLevel:[FileReader getStartOfLevel:lvlNum atPath:lvlPack] atPath:lvlPack]);
CCSprite *spriteToMake;
int start = [FileReader getStartOfLevel:lvlNum atPath:lvlPack];
int length = [FileReader getLengthOfLevel:start atPath:lvlPack];
NSString *tmp = [FileReader getLineFromFile:lvlPack byIndex:start];
NSArray *tmpArray = [tmp componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSMutableArray *tmpArray2 = [tmpArray mutableCopy];
[tmpArray2 removeObject:#""];
requiredLinks = [(NSString*)[tmpArray2 objectAtIndex:2] intValue];
[tmpArray2 release];
for(int i = start + 1; i <= start + length; i++){
NSString *line = [FileReader getLineFromFile:lvlPack byIndex:i];
int x = 0;
int y = 0;
NSArray *temp = [line componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSMutableArray *temp2 = [temp mutableCopy];
[temp2 removeObject:#""];
//Determine the type of sprite
if([(NSString*)[temp2 objectAtIndex:0] isEqualToString:#"Basic_Sprite"]){
spriteToMake = [BasicLink sprite];
}else if([(NSString*)[temp2 objectAtIndex:0] isEqualToString:#"Big_Sprite"]){
spriteToMake = [BasicLink spriteWithFile:#"Big_Link.png"];
}else{
spriteToMake = nil;
}
//Create the sprite
if(spriteToMake != nil){
x = [(NSString*)[temp2 objectAtIndex:1] intValue];
y = [(NSString*)[temp2 objectAtIndex:2] intValue];
spriteToMake.position = ccp(x, y);
NSLog(#"%#", spriteToMake);
[self addChild:spriteToMake];
[spriteToMake setUpdate];
}else{
NSLog(#"Sprite set to NULL");
}
NSLog(#"%i, %i, %i", x, y, [temp2 count]);
[temp2 release];
}
}
And here's the subclass' header:
#interface BasicLink : CCSprite{
CGPoint position;
CGPoint movement;
int explosionRadius, width, height;
CCScene *sceneIn;
}
#property (assign)CGPoint pos, movement;
#property (assign)int explosionRadius, width, height;
#property (assign)CCScene* sceneIn;
+(CCSprite*)sprite;
+(CCSprite*)spriteAtX:(int)x atY: (int)y;
-(void)die;
-(void)explode;
-(void)updateSprite;
-(CGRect)getBounds;
-(void)setUpdate;
-(void)move:(int)x, int(y);
#end
And here's the part of the subclass that initializes the sprite:
#implementation BasicLink
#synthesize position, movement, explosionRadius, sceneIn, width, height;
+(CCSprite*)sprite{
return [BasicLink spriteWithFile:#"Basic_Link.png"];
}
Any help is appreciated.
Here's an obvious problem:
-(void)move:(int)x, int(y);
In C, the comma is an operator. The compiler interprets this statement as this method declaration:
- (void)move:(int)x
I'm not entirely certain what it's doing with int(y); it's possibly treating it as a C function declaration. In any case, it isn't part of the method declaration.
Your move declaration should look like this:
- (void)moveToX:(int)x andY:(int)y;
Another minor mistake is the return type of your class methods:
+(CCSprite*)sprite{
return [BasicLink spriteWithFile:#"Basic_Link.png"];
}
That should be:
+ (BasicLink *)sprite{
return [BasicLink spriteWithFile:#"Basic_Link.png"];
}
That's probably not your problem here, though.

EXC_BAD_ACCESS on getting value from NSValue

I'm constructing a series of MKPolygons and storing them in an array of NSValues:
for (NSDictionary* country in countries) {
NSMutableArray* polygons = [[NSMutableArray alloc] init];
for (NSArray* polygon in [country objectForKey:#"polygons"]) {
CLLocationCoordinate2D polygonCoords[polygon.count];
int i;
for (i = 0; i < polygon.count; i++) {
NSValue* coords = [polygon objectAtIndex:i];
CLLocationCoordinate2D stored_coords;
[coords getValue:&stored_coords];
polygonCoords[i] = stored_coords;
}
MKPolygon* poly = [MKPolygon polygonWithCoordinates:polygonCoords count:polygon.count];
[polygons addObject:[NSValue valueWithBytes:&poly objCType:#encode(MKPolygon)]];
[chillPillMap addOverlay:poly];
}
[country setValue:polygons forKey:#"polygon_objects"];
}
However, when I try to access them later, I get two or three in and a EXC_BAD_ACCESS occurs:
for (NSDictionary* country in countries) {
NSArray* polygon_objects = [country objectForKey:#"polygon_objects"];
int i;
for (i = 0; i < polygon_objects.count; i++) {
MKPolygon* saved_poly = [MKPolygon alloc];
[[polygon_objects objectAtIndex:i] getValue:&saved_poly];
}
}
Not sure why this is.
MKPolygon is an objective-C object. You can put it into the array without converting it to a NSValue. Furthermore, you are telling NSValue to take the value of the bytes, but you are passing it the address of the pointer. Bad news.
Why not just...
[polygons addObject:poly]
then...
MKPolygon *saved_poly = [polygon_objects objectAtIndex:i];

Make variable name out of NSString

I have got a for loop where 9 hexagons (hexagon1 through hexagon9) have to be created... But I cannot use hexString as the name of the Sprite because it is a NSString, right ? So how would I make it right ?
hexString [<- I want the for loop to generate "hexagon1", then "hexagon2" and so on instead of the NSString] = [self createHexagon:ccp(xVal,yVal) :i];
int hexCount = [[[itemPositions valueForKey:myString]valueForKey:#"hexposition"] count];
for (int i=1;i<=hexCount;i++){
NSString *hexString = [NSString stringWithFormat:#"hexagon%d",i];
NSNumber *generatedXVal = [[[[itemPositions valueForKey: myString ]valueForKey:#"hexposition"] valueForKey: hexString]valueForKey: #"xVal"];
int xVal = [generatedXVal integerValue];
NSNumber *generatedYVal = [[[[itemPositions valueForKey: myString ]valueForKey:#"hexposition"] valueForKey: hexString ]valueForKey: #"yVal"];
int yVal = [generatedYVal integerValue];
hexString = [self createHexagon:ccp(xVal,yVal) : i];
NSLog(#"%#", hexString);
}
That would be impossible as you didn't declare the variable. A work around for this would be using an NSArray and saving your data on to the array instead of making a list of variables.
Use NSMutableDictionary.
for (int i=1;i<=hexCount;i++){
NSString *hexString = [NSString stringWithFormat:#"hexagon%d",i];
CCSprite *sprite = [self doSomethingToGetSprite];
[mutableDictionary setObject:sprite forKey:hexString];
}
Later you can iterate over all the sprites in the dictionary using:
for (NSString *key in mutableDictionary) {
CCSprite *sprite = [mutableDictionary objectForKey:key];
[self doStuffWithSprite:sprite];
}
By the way, why are you overwriting hexString that you assign here:
NSString *hexString = [NSString stringWithFormat:#"hexagon%d",i];
With the one here:
hexString = [self createHexagon:ccp(xVal,yVal) : i];
And that method call is an obvious syntax error with the dangling : i part there.
can you use NSSelectorFromString?