Xcode cannot recognize generic methods

In objective-c, I created a category, like

@interface NSArray <__covariant ObjectType> (ppEx)
@end

Look at this ObjectType, I wrote a method like - (NSArray *)pp_map:(id(^)(ObjectType element))block;which act like the map function in Swift. you can call it like

NSArray <NSString *>*values = @[@"1", @"2", @"3", @"4"];
NSArray *valueMap = [values pp_map:^id _Nonnull(NSString * _Nonnull element) {
    return [NSString stringWithFormat:@"Hello %@", element];
}];

Now I need to add a property like mapBlock, I want to realize the same func;

@property (nonatomic, copy) NSArray *(^mapBlock)(id(^paramBlock)(ObjectType element));

I did it. But when I call this method in Xcode, it can't complete automatically.

values.mapBlock(^id _Nonnull(ObjectType  _Nonnull element) {

})

It's unable to recognize type NSString, and always show ObjectType which can cause error. I can manually change it to NSString, but it's too complicated. I think it's a problem of Xcode. Can anybody help me?

There are disconnects between the lightweight generic system used by Objective-C, which is compile-time only, and the more full-feature generic system used by Swift. You’ve found one. The fundamental issue is that, when you work with NSArray, Swift isn’t aware of the element type. For example:

let a = NSArray(object: "Hello Cruel World!")
let e = a.firstObject!

The type of e is Any. Moreover, you can’t fix this by tweaking the types because NSArray is not generic in Swift. If you want a generic array in Swift, you’re expect to use Array.

The standard solution here is to apply a lightweight generic annotation to the Objective-C code that vends the array. That allows Swift to import it as an appropriately typed array. Contrast this:

- (NSArray *)returnsArray;

which is imported as returning [Any] with this:

- (NSArray<NSString *> *)returnsArrayOfStrings;

which returns [String].

So, rather than try to get your -pp_map: method to import cleanly into Swift, I recommend that you import your arrays cleanly into Swift, at which point you can use Swift’s native map(_:) method.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Xcode cannot recognize generic methods
 
 
Q