Reputation: 5823
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
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
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