Open felix-dumit opened 8 years ago
@felix-dumit Thank you for letting me know. I've never noticed on Bolts' update.
I'm not familiar with new generics feature with Objective-C.
IIRC, specifying concrete type instead of id
doesn't cause any errors or warnings on Xcode 6.4, on which generics is not supported.
Now on Xcode 7 with generics, are there any problems?
No there are no issues. I just wanted to see if we could find a solution to automatically infer the parameter type of the result.
I would like to make it clear that we should do about this. Are you saying about autocomplete/snippet related things? If so, I have no idea at this time.
Anyway, I'll give it a try to use Bolts with generics. Let me have a time.
Basically it relates to the block parameter. Currently it is as id
and we can cast to anything we want, but it's not as safe as if the block parameter was of the generic type.
I haven't played much with generics in Bolts as well so I'll also be taking a look.
Ah, I've almost understood. When I write a code like:
BFTask<NSString*> *task = [BFTask taskWithResult:@"hello"];
task.then(^id(NSNumber* result){ // type mismatch!
//
});
it is nice that an error or a warning is reported.
I took a little try Bolts with generics. (pure Bolts, not used with our extensions)
In Xcode 7, the code below produces no errors/warnings (expected):
BFTask<NSString *> *task = [BFTask taskWithResult:@"Hey"];
[task continueWithBlock:^id(BFTask<NSString *> *task) {
// ...
}];
And this produces no errors/warnings, too (unexpected):
BFTask<NSString *> *task = [BFTask taskWithResult:@"Hey"];
[task continueWithBlock:^id(BFTask<NSNumber *> *task) {
// ...
}];
continueWithBlock:
takes a block whose type is BFContinuationBlock
.
BFContinuationBlock
is defined here.
After expanding BF_GENERIC
macro, it should become like this.
@interface BFTask <__covariant BFGenericType> : NSObject
typedef id(^BFContinuationBlock)(BFTask <BFGenericType> *task);
// ...
@end
Is the type of block parameter not checked? I don't know much about Objective-C generics. :confused:
By the way, I found that if type parameter was strictly checked, chaining the block had a problem. continueWithBlock
returns instancetype
. So same BFGenericType
type parameter should be used.
The code below uses unmatched type because the first continueWithBlock
returns BFTask<NSString *>
.
BFTask<NSString *> *task = [BFTask taskWithResult:@"Hey"];
[[task continueWithBlock:^id(BFTask<NSString *> *task) {
// returns NSNumber
return @100;
}] continueWithBlock:^id(BFTask<NSNumber *> *task) {
// ...
}];
I took a look at Bolts-Java, two type parameters were used there.
public class Task<TResult> {
// ...
public <TContinuationResult> Task<TContinuationResult> continueWith(
Continuation<TResult, TContinuationResult> continuation) {
// ...
}
// ...
}
What's the best way :disappointed_relieved:
I tried to play around with it and add some BF_GENERIC to our methods but without any luck. I guess we keep it as is then
With the new update to Bolts we can do something like this:
BFTask<NSString*> *task = [BFTask taskWithResult:@"hello"];
Can we add support so that when we call the
.then
method instead ofid
we correctly infer the parameter type of result: