mary_nate
(Mary Nate)
March 4, 2014, 3:26am
1
Some Obj-C libraries expose API by macro (e.g. ReactiveCocoa / extobjc):
RAC(self, loggedIn) = [[NSNotificationCenter.defaultCenter
rac_addObserverForName:UserDidLogOutNotification object:nil]
mapReplace:@NO];
In this code snippet, RAC is a macro defined by ReactiveCocoa which use other macros:
#define RAC(TARGET, ...) \
metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__)) \
(RAC_(TARGET, __VA_ARGS__, nil)) \
(RAC_(TARGET, __VA_ARGS__))
It’s unpractical to manually expand the macro for every API call.
As this issue also apply to Oxygen and I wonder what might be the best solution? ( Use cpp pre-processor or maybe writing custom Cirrus Aspect? )
Thanks.
ck
(Carlo Kok)
March 5, 2014, 7:00am
2
Can you show the full thing? I need to see what it really does before I can recommend a workaround.
mary_nate
(Mary Nate)
March 5, 2014, 7:37am
3
ck
(Carlo Kok)
March 5, 2014, 8:19am
4
An inline method, or a method call aspect might work. This particular macro seems to abuse variadic arguments to the max though.
#define RAC_(TARGET, KEYPATH, NILVALUE) \
[[RACSubscriptingAssignmentTrampoline alloc] initWithTarget:(TARGET) nilValue:(NILVALUE)][@keypath(TARGET, KEYPATH)]
a simple method that takes a selector could work too though, If I read this right.
mary_nate
(Mary Nate)
March 5, 2014, 8:38am
5
I end up with a helper class:
public static class RAC
{
public static RACSignal RAC(NSObject target, NSString keypath, RACSignal signal) {
new RACSubscriptingAssignmentTrampoline(target) nilValue(null).setObject(signal) forKeyedSubscript(keypath);
}
}
So
RAC(self, createEnabled) = [RACSignal
combineLatest:@[ RACObserve(self, password), RACObserve(self, passwordConfirmation) ]
reduce:^(NSString *password, NSString *passwordConfirm) {
return @([passwordConfirm isEqualToString:password]);
}];
Can be wrote as something like:
RAC.RAC(self, "createEnabled",
RACSignal.combineLatest( {} )
reduce ( (password, passwordConfirm) => {
return passwordConfirm == password;
}));
But it failed to compiled. The method declaration of RACSignal::combineLatest:reduce is:
public static ReactiveCocoa.RACSignal combineLatest(this ReactiveCocoa.RACSignal @this, Foundation.INSFastEnumeration signals) reduce(delegate rtl.id() reduceBlock);
Pls note that reduce take “delegate rtl.id ()” as argument. So there’s no way to pass arguments to the block since the signature mismatch.
ck
(Carlo Kok)
March 6, 2014, 7:12am
6
Indeed not. As to your other thread it’s to do with the special block, I’ll have a look at that.