2

Feeling slightly witty the other day, I wrote an eachWithIndex: method in a NSArray category. It has a typedef like this:

typedef void (^processItem)(id item, int index);

and the method looks like this:

- (void)eachWithIndex:(processItem)block {
    for (int i=0; i<self.count; i++) {
        id item = [self objectAtIndex:i];
        block(item, i);
    }
}

However, if my block contains a return at any point, it doesn't jump out of the calling method (nor the block). Consider this code in Ruby:

def blah
    %w{one two three}.each_with_index {|thing, i| puts "#{i}=#{thing}"; return "hello!" if i==1 }
    puts "blah does more stuff"
end

when i reaches one, the blah method will end. This does not happen in Obj-C, and I feel that it should. Are blocks more integrated into Ruby than Objective-C?

1

1 Answer 1

2

It isn't really a matter of integration or being second class citizens. They simply work in different ways. Blocks are separate functions in effect, so have their own scope in which return works. Return will exit the block, but not the calling method/function, just as if you called another method or function. This provides a lot of consistency

In order to stop your method you need to pass in a BOOL pointer that can be set as to YES to stop the array. Look at NSArray's enumerateObjectsUsingBlock: method that does essentially the same thing as your each with index method (and is probably better to use as it already exists and will most likely be better optimised).

1
  • Thanks for that, hadn't noticed the enumerateObjectsUsingBlock and wouldn't have thought to use a pointer to a BOOL... very very cool. Nov 5, 2011 at 11:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.