hzxu
hzxu

Reputation: 5823

What is the syntax/signature of a Objective-C method that returns a block without typedef?

I defined a block that takes an NSString and returns a NSURL for that string:

id (^)(id obj)

I've used typedef to make it a block with a name:

typedef id (^URLTransformer)(id);

And the following method does not work:

+ (URLTransformer)transformerToUrlWithString:(NSString *)urlStr
{
    return Block_copy(^(id obj){
        if ([obj isKindOfClass:NSString.class])
        {
            NSString *urlStr = obj;
            return [NSURL URLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
        }
        return nil; // **THIS LINE FAILS**
    });
}

Error:

Return type 'void *' must match previous return type 'id' when block literal has unspecified explicit return type

My question is: 1. how to correctly implement the method 2. how to implement the method without typedef URLTransformer?

Thanks

Upvotes: 3

Views: 1466

Answers (2)

Bryan Chen
Bryan Chen

Reputation: 46598

1.

You can either cast it to id or add type to block. I asked similar question before and quote from the answer

The correct way to remove that error is to provide a return type for the block literal:

id (^block)(void) = ^id{
    return nil; 
};

in your case

+ (URLTransformer)transformerToUrlWithString:(NSString *)urlStr
{
    return Block_copy(^id(id obj){ // id here
        if ([obj isKindOfClass:NSString.class])
        {
            NSString *urlStr = obj;
            return [NSURL URLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
        }
        return nil; // id here
    });
}

or

+ (URLTransformer)transformerToUrlWithString:(NSString *)urlStr
{
    return Block_copy(^(id obj){
        if ([obj isKindOfClass:NSString.class])
        {
            NSString *urlStr = obj;
            return [NSURL URLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
        }
        return (id)nil; // **THIS LINE FAILS**
    });
}

2.

To return block without typedef you can use similar syntax to return function pointer

+ (id (^)(id))transformerToUrlWithString:(NSString *)urlStr;

You can check more example from here.

PS: You should avoid Block_copy in ObjC code, use [block copy].

PS2: You mush be using ARC (otherwise so many leaks) and you don't need to copy block explicitly (in 99% of the cases, which includes this one).

PS3: Your should avoid id as much as possible, so your block should be typedef NSURL *(^URLTransformer)(NSString *);

Upvotes: 3

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726579

You can avoid typedef like this:

@interface Blah : NSObject
+(id (^)(id)) blockret;
@end

@implementation Blah
+(id (^)(id)) blockret {
    return ^(id obj) {
        return @"helo";
    };
}
@end

The type of your block is id (^)(id) - that's what goes into parentheses after the plus.

Upvotes: 2

Related Questions