I’m trying to make a good block-based initializer for an objective-c class. I’m declaring it in a superclass and I want it to be useful in all subclasses.
Right now I have:
+ (id)createWithBlock:(void (^) (id newObject))creationBlock {
id newObject = [self object];
creationBlock(newObject);
return newObject;
}
Which can be used (in a subclass) as such:
Record *newRecord = [Record createWithBlock:^(id newObject) {
Record *newRecord = (Record *)newObject;
newRecord.name = @"Ginger";
newRecord.type = @"Rhizome";
}];
This is okay for now, but I’d love to get this pared down a bit. Ideally it would look like:
Record *newRecord = [Record createWithBlock:^{
name = @"Ginger";
type = @"Rhizome";
}];
But that seems a bit ambitious. I would also be okay with just:
Record *newRecord = [Record createWithBlock:^(Record *newRecord) {
newRecord.name = @"Ginger";
newRecord.type = @"Rhizome";
}];
This last version is difficult because it seems clang does some compile-time type checking for blocks. The above won’t compile with the definition of createWithBlock: that I have above, because: incompatible block pointer types initializing 'void (^)(struct Record *)', expected 'void (^)(struct objc_object *).
If it didn’t do this strong type checking I could just swizzle the methods at runtime. (Or maybe I could do that right now if I typedef my block declaration?)
I’ve been scratching my head on this for a while, and I’ve read pretty much every document on blocks I could find, including the clang spec. If anyone has ideas I’d love to hear them, this is for an open source project and I think the pattern would benefit all objective-c users.
Right now my thoughts are leaning towards imp_implementationWithBlock(). But then I’d need to “construct” a new IMP based on what’s in that one, and swap it out. Feasible?
What compiler are you using? I believe recent versions of LLVM will accept the last code example you give. (i.e. The error you give shouldn’t happen.)
In particular, this works for me with LLVM 3.1 in a brand-new Xcode project in Xcode 4.3.3.