Getting CGRect from array - objective-c

For my application I am trying to store CGRect objects into an NSMutableArray. It is loading well and printing in the log statement, but trying to take the CGRects from the array shows an error. Here is a code snippet:
CGRect lineRact = CGRectMake([[attributeDict objectForKey:#"x"] floatValue],
[[attributeDict objectForKey:#"y"] floatValue],
[[attributeDict objectForKey:#"width"] floatValue],
[[attributeDict objectForKey:#"height"] floatValue]);
[lineRactangle addObject:NSStringFromCGRect(lineRact)];
How can I get the rects back from the array?

A CGRect is a struct, not an object, and thus cannot be stored in NSArrays or NSDictionaries. You can turn it into a string and turn that string back into a CGRect, but the best way is to encapsulate it via an NSValue:
NSValue *myValue = [NSValue valueWithCGRect:myCGRect];
You can then store this NSValue object in arrays and dictionaries. To turn it back into a CGRect, you'd do:
CGRect myOtherCGRect = [myValue CGRectValue];

[lineRactangle addObject:[NSValue valueWithCGRect:lineRect]];

Use NSValue to wrap CGRect thus store them in NSArrays.
For example:
CGRect r = CGRectMake(1,2,3,4);
NSValue *v = [NSValue valueWithCGRect:rect];
NSArray *a = [NSArray arrayWithObject:v];
CGRect r2 = [[a lastObject] CGRectValue];
See documentation for the other supported structures.

Actually, I don't think any of the answers thus far really address the question ajay asked. The short answer is: You need to supply CGRectMake with the intValue, rather than the floatValue of the dictionary item. If you need to do this for several CGRects, here's a suggested method:
- (CGRect) NSArrayToCGRect: (NSDictionary *) attributeDict
{
int x = [[attributeDict objectForKey:#"x"] intValue];
int y = [[attributeDict objectForKey:#"y"] intValue];
int w = [[attributeDict objectForKey:#"width"] intValue];
int h = [[attributeDict objectForKey:#"height"] intValue];
return CGRectFromString([NSString stringWithFormat: #"{{%d,%d},{%d,%d}}", x, y, w, h]);
}
There may be a more elegant way to accomplish this, but the above code does work.

If your object can be set with ".frame" you could use:
// {{CGFloat x,CGFloat y}, {CGFloat width,CGFloat height}}
NSString *objectCoords = #"{{116,371},{85,42}}";
myObject.frame = CGRectFromString(objectcoords);
or for multiple objects:
NSArray *objectCoords = [NSArray arrayWithObjects:
#"{{116,371},{85,42}}",
#"{{173,43},{85,42}}",
#"{{145,200},{85,42}}",
nil];
myObject1.frame = CGRectFromString([objectCoords objectAtIndex:0]);
myObject2.frame = CGRectFromString([objectCoords objectAtIndex:1]);
myObject3.frame = CGRectFromString([objectCoords objectAtIndex:2]);

CGRect is a struct you cannot put it in an NSArray. You can only add objects to it.

or something more 'extreme'... creating an array that holds arrays of CGRect(s)
movPosTable = [[NSArray alloc] initWithObjects:
[[NSArray alloc] initWithObjects: [NSValue valueWithCGRect:[GridAB frame]], [NSValue valueWithCGRect:[GridBA frame]], [NSValue valueWithCGRect:[GridBB frame]], nil],
[[NSArray alloc] initWithObjects: [NSValue valueWithCGRect:[GridAA frame]], [NSValue valueWithCGRect:[GridAC frame]], [NSValue valueWithCGRect:[GridBA frame]], [NSValue valueWithCGRect:[GridBB frame]], [NSValue valueWithCGRect:[GridBC frame]], nil],
[[NSArray alloc] initWithObjects: [NSValue valueWithCGRect:[GridAB frame]], [NSValue valueWithCGRect:[GridBB frame]], [NSValue valueWithCGRect:[GridBC frame]], nil], nil];
where 'GridAA', 'GridAB' etc. correspond to UIViews

Related

Get CGRect from NSStringFromCGRect

I stored a frame (CGRect) in a NSStringFromCGRect, how do I later retrieve the rect?
[mDict setObject:NSStringFromCGRect(frame) forKey:#"frame"];
I need to get the data back how?
CGRect frame = [[mDict objectForKey:#"frame"] ..?]
Does a method exist or I have to parse the string manually?
I think you are looking for,
CGRect frame = CGRectFromString([mDict objectForKey:#"frame"]);
I recommend to use NSValue instead of creating a string representation.
NSValue instances are objects and can be put into a dictionary
CGRect frame = CGRectMake(0.0, 0.0, 100.0, 100.0);
NSValue *value = [NSValue valueWithRect:(NSRect)frame];
NSDictionary *dict = #{#"frame" : value};
CGRect frameBack = (CGRect)[dict[#"frame"] rectValue];
NSLog(#"%#", NSStringFromRect(frameBack));
If you need a string representation which is easily reversible, you could use this
CGRect frame = CGRectMake(0.0, 0.0, 100., 100.0);
NSValue *value = [NSValue valueWithRect:(NSRect)frame];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:value];
NSString *base64String = [data base64EncodedStringWithOptions:0];
NSLog(#"%#", base64String);
NSData *dataBack = [[NSData alloc] initWithBase64Encoding:base64String];
NSValue *valueBack = (NSValue *)[NSKeyedUnarchiver unarchiveObjectWithData:dataBack];
CGRect frameBack = (CGRect)[valueBack rectValue];
NSLog(#"%#", NSStringFromRect(frameBack));
Until someone find a better solution this is what I came up with:
-(CGRect) CGRectFromNStringFromCGRect: (NSString *) string {
NSString *newString = [string stringByReplacingOccurrencesOfString:#"{" withString:#""];
newString = [newString stringByReplacingOccurrencesOfString:#"}" withString:#""];
newString = [newString stringByReplacingOccurrencesOfString:#" " withString:#""];
NSArray *array = [newString componentsSeparatedByString:#","];
if ([array count]==4) {
return CGRectMake([array[0] floatValue], [array[1] floatValue], [array[2] floatValue], [array[3] floatValue]);
} else {
return CGRectZero;
}
}
Use Like this:
CGRect frame = [self CGRectFromNStringFromCGRect:[mDict objectForKey:#"frame"];

Convert NSarray to twodimensional array

I have a an one dimensional array which contains a vary numbers of object (depending on the userinput)
The NSArray is called homePlayersArray. This could example contain 2, 3, 5, 6, 4
The thing is i want to convert this to a two dimensional array where example.
{2,0}, {3,}, {5,0}, {6,0},{4,0}
the first value in the object will me by NSarray (called homepPlayersArray) and the second value will be 0.
What is the best way to obtain this?
//Your original array
NSArray *homePlayersArray = [[NSArray alloc] initWithObjects:
[NSNumber numberWithInt:2],
[NSNumber numberWithInt:3],
[NSNumber numberWithInt:5],
[NSNumber numberWithInt:6],
[NSNumber numberWithInt:4],nil];
//For your 2D array
NSMutableArray *secondArray = [[NSMutableArray alloc] initWithCapacity:[homePlayersArray count]];
//populate as required
for(int i=0;i<[homePlayersArray count];i++){
NSArray *tempArray = [[NSArray alloc] initWithObjects:[homePlayersArray objectAtIndex:i],[NSNumber numberWithInt:0], nil];
[secondArray addObject:tempArray];
}
//print out some results to show it worked
NSLog(#"%#%#",#"secondArray first object value 0: ",[[secondArray objectAtIndex:0] objectAtIndex:0] );
NSLog(#"%#%#",#"secondArray first object value 1: ",[[secondArray objectAtIndex:0] objectAtIndex:1] );
NSLog(#"%#%#",#"secondArray second object value 0: ",[[secondArray objectAtIndex:1] objectAtIndex:0] );
NSLog(#"%#%#",#"secondArray second object value 1: ",[[secondArray objectAtIndex:1] objectAtIndex:1] );

Storing UIColors in NSDictionary and retrieving them?

I need to return a specific UIColor for a given index.
I am trying to basically store the UIColors as NSArrays
TypeColors = [[NSDictionary alloc] initWithObjectsAndKeys:
#"1", [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.5],[NSNumber numberWithFloat:0.5],[NSNumber
numberWithFloat:0.5],[NSNumber numberWithFloat:1.0], nil],
#"5", [NSArray arrayWithObjects:[NSNumber numberWithFloat:1.0],[NSNumber
numberWithFloat:0.5],[NSNumber numberWithFloat:0.1],[NSNumber
numberWithFloat:1.0], nil]
, nil]; //nil to signify end of objects and keys.
And here I want to retrieve the UIColor back from that dictionary:
a = 5;
NSArray* colorArray = [TypeColors objectForKey:a];
UIColor* color = [UIColor colorWithRed:[colorArray objectAtIndex:0]
green:[colorArray objectAtIndex:1] blue:[colorArray objectAtIndex:2]
alpha:[colorArray objectAtIndex:3]];
It always returns me a zero, anyone knows why?
Thanks!
Change it to
UIColor* color = [UIColor colorWithRed:[[colorArray objectAtIndex:0] floatValue]
green:[[colorArray objectAtIndex:1] floatValue] blue:[[colorArray objectAtIndex:2] floatValue]
alpha:[[colorArray objectAtIndex:3] floatValue]];
The parameter to be sent there is cgfloat and not NSNumber
Two things:
1) The order of things in initWithObjectsAndKeys are objects and then their keys. Yes, it is intuitively backwards.
2) The key is not an integer 5 but an NSString #"5".
You need to convert your UIcolor to Nsstring first before save it in dictionary as follow :
-(NSString *)convertColorToString :(UIColor *)colorname
{
if(colorname==[UIColor whiteColor] )
{
colorname= [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
}
else if(colorname==[UIColor blackColor])
{
colorname= [UIColor colorWithRed:0 green:0 blue:0 alpha:1];
}
else
{
colorname=colorname;
}
CGColorRef colorRef = colorname.CGColor;
NSString *colorString;
colorString=[CIColor colorWithCGColor:colorRef].stringRepresentation;
return colorString;
}
and when you want to fetch the value from dictionary than you need to convert string to color as follow
-(UIColor *)convertStringToColor :(NSDictionary *)dicname :(NSString *)keyname
{
CIColor *coreColor = [CIColor colorWithString:[dicname valueForKey:keyname]];
UIColor *color = [UIColor colorWithRed:coreColor.red green:coreColor.green blue:coreColor.blue alpha:coreColor.alpha];
//NSLog(#"color name :%#",color);
return color;
}
exa :
here dicSaveAllUIupdate is my dictionary and i saved my view background color in it.
[dicSaveAllUIupdate setObject:[self convertColorToString: self.view.backgroundColor] forKey:#"MAINVW_BGCOLOR"];
and i will retrive it as follow
self.view.backgroundColor=[self convertStringToColor:retrievedDictionary:#"MAINVW_BGCOLOR"];
Hope this help to you ...

How to return an array

I need to return an array but don't know how to do this, here is how it looks
CGPoint position[] = {
CGPointMake(500, 200),
CGPointMake(500, 200)
};
return position;
But I get an error of incompatible result. Any way around this error? Need to return multiple positions.
You can do something like this
NSArray *position = [NSArray arrayWithObjects:
[NSValue valueWithCGPoint:CGPointMake(500, 200)],
[NSValue valueWithCGPoint:CGPointMake(600, 300)],
nil];
for getting the values from array
for(int i=0; i<[position count]; i++) {
NSValue *value = [position objectAtIndex:i];
CGPoint point = [value CGPointValue];
NSLog(#"%#",NSStringFromCGPoint(point);
}
With UIKit Apple added support for CGPoint to NSValue, so you can do:
NSArray *points = [NSArray arrayWithObjects:
[NSValue valueWithCGPoint:CGPointMake(5.5, 6.6)],
[NSValue valueWithCGPoint:CGPointMake(7.7, 8.8)],
nil];
List as many [NSValue] instances as you have CGPoint, and end the list in nil. All objects in this structure are auto-released.
On the flip side, when you're pulling the values out of the array:
NSValue *val = [points objectAtIndex:0];
CGPoint p = [val CGPointValue];
If you don't want to use NSArray and since CGPoint is a struct you can return it the C way
CGPoint *position = malloc(sizeof(CGPoint)*2);
position[0] = CGPointMake(500,200);
position[1] = CGPointMake(500,200);
return position;
although the drawback is that the calling function doesn't know the number of elements in the array, you may need to tell this in some other manner.
also you need to free the returning array once you are done with it using free();
although using NSArray/NSMutableArray is more convenient.

How to filter CGPoints in an NSArray by CGRect

I have an NSArray with CGPoints. I'd like to filter this array by only including points within a rect.
How can I formulate an NSPredicate such that each point satisfies this predicate:
CGRectContainsPoint(windowRect, point);
Here's the code so far:
NSArray *points = [NSArray arrayWithObjects: [NSValue valueWithCGPoint:pointAtYZero] ,
[NSValue valueWithCGPoint:pointAtYHeight],
[NSValue valueWithCGPoint:pointAtXZero],
[NSValue valueWithCGPoint:pointAtXWidth],
nil];
NSPredicate *inWindowPredicate = [NSPredicate predicateWithFormat:#"CGRectContainsPoint(windowRect, [point CGPointValue])"];
NSArray *filteredPoints = [points filteredArrayUsingPredicate:inWindowPredicate];
You cannot do this with the predicate format syntax, but you can use a block:
NSArray *points = ...;
CGRect windowRect = ...;
NSPredicate *inWindowPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
CGPoint point = [evaluatedObject CGPointValue];
return CGRectContainsPoint(windowRect, point);
}];
NSArray *filteredPoints = [points filteredArrayUsingPredicate:inWindowPredicate];
Note that it's not possible to use block-based predicates for Core Data fetch requests.