views:

128

answers:

4

Basically I'm sorting through objects in an array by y value (The furthest down the page is at the start of the array) but I'm having a bit of trouble. I assign all of the UIImageViews in an array a value:

for (UIImageView *Blocky in objectsArray){
  [Blocky.layer setValue:[NSString stringWithFormat: @"%f",
                                     Blocky.center.y] forKey:@"value"];
}

Because it's a UIImageView I have to put layer after "Blocky" otherwise I get the following error:

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIImageView 0x3d44880> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key value.'

My problem is when I'm sorting it I don't know where to put the ".layer" so I get the same problem because UIImageViews can't deal with keys on there own. Here is my sorting code:

NSSortDescriptor *sortDescriptor =
  [[NSSortDescriptor alloc] initWithKey:@"value" ascending:YES];
[objectsArray sortUsingDescriptors:[NSArray
                                    arrayWithObject:sortDescriptor]];
[sortDescriptor release];

Thanks in advance, Ozzie

A: 

Are you sure CALayer is supposed to accept arbitrary KVC keys? This looks wrong to me.

Shouldn't you extract the heights to a buffer of structures and qsort that?

eg

I think it would be something like this:

//
// before @implementation sections
//
typedef struct __MySortEntry {
  UIImageView* image;
  CGFloat height;
} MySortEntry, *PMySortEntry;

static int compareMySortEntry (const void * a, const void * b)
{
  CGFloat temp =( ((PMySortEntry)a)->height - ((PMySortEntry)b)->height );
  return (temp<0)?-1:(temp>0)?1:0;
}

//
// in @implementation section somewhere
//
NSMutableData* mutable = [[NSMutableData alloc] initWithLength:
  sizeof(MySortEntry)*objectsArray.count];
PMySortEntry entries = (PMySortEntry)mutable.mutableBytes;
for (int c = 0; c < objectsArray.count; c++) {
  entries[c].image = (UIImageView*)[objectsArray objectAtIndex:c];
  entries[c].height = entries[c].image.center.y;
}

qsort(entries, objectArray.count, sizeof(MySortEntry), compareMySortEntry);

for (int c=0; c < objectArray.count; c++) {
  UIImage* imageInSequence = entries[c].image;
  // do something with images **in sequence**
}
[mutable release];

Edit: Changed center.y to size.height.

Edit: Changed size.height back to center.y. Oops.

Edit: Changed UIImage to UIImageView.

martinr
Sorry! By height I meant which has the greatest y value rather than the largest image
Ozzie
CALayers are key-value coding compliant container classes, so they are built to accept arbitrary keys and values.
Brad Larson
A: 

Use the NSMutableArray sortUsingFunction:context: method:

// top of file
static NSInteger compareImageHeights(id image1, id image2, void* context) {
  CGFloat temp = ((UIImageView*)image2).center.y - ((UIImageView*)image1).center.y;
  return (temp>0)?NSOrderedAscending:(temp<0)?NSOrderedDescending:NSOrderedSame;
}
// within file somewhere
[objectsArray sortUsingFunction:compareImageHeights context:NULL];

The reason the function is required (and you can't just use sortUsingSelector: or sortUsingSortDescriptor:) is that you can't specify a KVC key to identify just the y component only as a sort variable.

Edit: Changed center.y to size.height.

Edit: Oops. Changed size.height back to center.y. Fixed type to UIImageView rather than UIImage. It seems KVC objects can in theory support arbitrary keys, but some will and some won't.

martinr
Actually, using keys in this manner is perfectly fine on a CALayer. CALayers are key-value coding compliant container classes, so they are built to accept arbitrary keys and values. See the "Layer Classes" section of the Core Animation Programming Guide: http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/WhatisCoreAnimation.html#//apple_ref/doc/uid/TP40004689
Brad Larson
A: 

Sorry guys. By height I meant which image is furthest down the page rather than which is the tallest. Thanks for the help though. It's a shame because i had the problem that you have solved before and it never got solved! Does anyone know how to order imageviews by which is furthest down the page?

Ozzie
A: 

Why not set the tag property on each view as you create them based on the height and retrieve them by tag?

David Sowsy