5
votes

I'm nesting blocks, and it looks UGGGGLY. Is there a way to write this less ugly? Mostly looking for syntax suggestions, rather than structural, but I'll accept either.

My block factory method,

-(NSImage *(^)(CGFloat size, BOOL preview))resizeBlock {

return (NSImage *(^)(CGFloat size, BOOL preview))[[^(CGFloat size, BOOL preview){
        // image-resizing code
        return [[[NSImage alloc] init] autorelease];
    } copy] autorelease];

}

Which is called from a number of functions similar to this,

-(void)queueResize:(CGFloat)targetSize toView:(NSImageView *)targetView {
    NSImage*(^sizeBlock)(CGFloat,BOOL) = [self resizeBlock];
    NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^(void) {
        NSImage *previewImage = (NSImage*)sizeBlock(targetSize,YES);
        targetView.image = previewImage;
    }];
    [queue addOperation:bo];
}

queue is an NSOperationQueue object. It won't compile without all the (ugly ugly) casting. Amidoinitrite?

Edit: As per Dave DeLong's answer, and http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/, I changed the line

targetView.image = previewImage;

to be,

[targetView performSelectorOnMainThread:@selector(setImage:) withObject:previewImage waitUntilDone:YES];
1
@Jesse, man don't playa hate, appreciate.Kenny Winker
Haha its my 'main' language, so i wasn't hating just joking around. As far as the code...it looks about as pretty as it can using blocks i believe, but not really an expert.Jesse Naugher
Is [self resizeBlock] called anywhere else in your program, or just in the queueResize:toView: method?Itai Ferber
@Jesse you'd have the same problem in C if you were using function pointers.Dave DeLong
@itai ferber, yeah i have a handful of methods that do different things with the resized image.Kenny Winker

1 Answers

6
votes

Use typedef:

typedef NSImage *(^KWResizerBlock)(CGFloat size, BOOL preview);

This makes your code become:

- (KWResizerBlock) resizeBlock {
  KWResizerBlock block = ^(CGFloat size, BOOL preview){
    // image-resizing code
    return [[[NSImage alloc] init] autorelease];
  };
  return [[block copy] autorelease];
}

-(void)queueResize:(CGFloat)targetSize toView:(NSImageView *)targetView {
  KWResizerBlock sizeBlock = [self resizeBlock];
  NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
    NSImage *previewImage = sizeBlock(targetSize, YES);
    //do something with previewImage
  }];
  [queue addOperation:bo];
}

One word of caution:

Your NSBlockOperation is going to be executing on a thread that's not the main thread, and so it is unsafe to manipulate any UI element from within that context. If you need to put the previewImage onto the UI, then you should dispatch_async() back to the main thread (or something functionally equivalent).

It may work right now, but it is strongly discourage and can lead to undefined behavior.