Saturday, October 6, 2012

Yet an other Objective-C block for fun

You know what, I could not live without blocks... It's sad but true.

Action blocks!

If you read all my previous block posts you now know how to use a block in a NSTimer. It's pretty neat and few people did take the time to say so in the comments which is great!

Now let's push the principle in the UI land. How about a block as target/action for any UIControl subclass ? That would be great not to have to write an other delegate method...

Example

Instead of this ...

- (void)viewDidLoad {
  ...
  UISegmentedControl *rightButtons = [[[UISegmentedControl alloc]initWithItems:@[UIBarButtonItemSearchImage, UIBarButtonItemSortbyImage]]autorelease];

  [rightButtons addTarget:self action:@selector(rightButtonPressed:) forControlEvents:UIControlEventValueChanged];
  ...
}

- (void)rightButtonPressed:(id)sender {
  /* Do this */
}

I prefer to write ...

__block UISegmentedControl *rightButtons = [[[UISegmentedControl alloc]initWithItems:@[UIBarButtonItemSearchImage, UIBarButtonItemSortbyImage]]autorelease];

id handler = [NSBlockOperation blockOperationWithBlock:^{ /* Do this */ }];

[rightButtons.layer setValue:handler forKey:@"_handler"]; // Retain the handler
[rightButtons addTarget:handler action:@selector(main) forControlEvents:UIControlEventValueChanged];

Since the UIResponder addTarget:action:forControlEvents: does not retain its target (unlike NSTimer), we store the block operation in the layer (every UI element has a layer). The main selector will run the block.

Now you may not find it as thrilling as the NSTimer trick but it still helps the reader figure the whole execution flow without requiring too much read-jumps.

No comments:

Post a Comment