Cindy
Cindy

Reputation: 57

In Objective-c, is a Block an object type?

In Objective-C, is a Block an object? Can it be retained/released? Can it be sub-classed?

Upvotes: 2

Views: 749

Answers (3)

i_am_jorf
i_am_jorf

Reputation: 54600

Lets look at this, for example:

- (void)doSomeStuffWithABlock 
{
    void(^myBlock)(NSUInteger, NSString *, NSString *) = ^(NSUInteger index, NSString *string, NSString *string) {
        // Do stuff
    };

    myBlock(1, @"two", @"three");  // Set breakpoint here to inspect myBlock.
}

In the debugger:

(lldb) po myBlock
<__NSMallocBlock__: 0x17d21f20>

(lldb) p * myBlock
(__block_literal_generic) $1 = 0x001cc801 MyApp`__68-[MyObject myMethod]_block_invoke + 1 at MYMyObject.m:218

(lldb) p (BOOL)[myBlock isKindOfClass:[NSObject class]]
(BOOL) $5 = YES

You can send it retain / release, if you're not using ARC. You can also ask for it's retainCount. However block.h declares these macros that you should use:

#define Block_copy(...) ((__typeof(__VA_ARGS__))_Block_copy((const void *)(__VA_ARGS__)))
#define Block_release(...) _Block_release((const void *)(__VA_ARGS__))

I don't think you can subclass it, since no headers publicly expose __NSMallocBlock__ or related Block types (see comments) (that I could find), and I suspect down that road lies nothing but the most excruciating pain, since you'll be trying to trick the compiler. I'm not sure why you'd even want to do that. If you need to add functionality, consider creating your own object that wraps a @property that is the actual block to execute. Or consider using NSBlockOperation.

Upvotes: 1

Gabriele Petronella
Gabriele Petronella

Reputation: 108101

Yes, it's an object type.

However it's mostly handled by the compiler, so you can't subclass it and you have very little control over memory management. You typically can only copy it to the heap, in case it outlives the scope it's declared in.

Concretely, at runtime a block is an instance of either __NSMallockBlock__, __NSStackBlock__ or __NSGlobalBlock__. You can read more on the subject here: http://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html

Upvotes: 5

Macmade
Macmade

Reputation: 53950

In addition to Gabriele's answer, which is correct, you can see it by sending a class message to a block:

#import <objc/message.h>

int main( void )
{
    void ( ^ block )( void ) = ^( void )
    {};

    NSLog( @"%@", ( ( id ( * )( id, SEL ) )objc_msgSend )( ( id )block, @selector( class ) ) );

    return 0;
}

A non-object type would eventually crash, but with a block, you'll get __NSGlobalBlock__ printed, meaning a block is a real (even if obviously special) instance of an Objective-C class.

Upvotes: 1

Related Questions