0

Given:

@interface NSArray (Sample)

@property (nonnull, nonatomic, readonly) NSArray *_Nonnull (^mapped)(id __nullable (^block)(id __nonnull));

@end

How can one implement this category? I'm confused by this block property syntax. This explains the type annotations: https://developer.apple.com/swift/blog/?id=25

This is what I started for implementation:

@implementation NSArray (Sample)

typedef id __nullable (^block)(id __nonnull);

...
@end

later tried this:

@implementation NSArray (Sample)

typedef NSArray *_Nonnull (^mapped)( id __nullable (^block)(id __nonnull) );

-(mapped)mapped {
    return ^( id __nullable (^block)(id __nonnull) ){
        return @[@"what", @"the", @"heck"];
    };
}
@end

Later still:

Technically I think the above would fulfill the extension's contract, but per the comments with bbum I have tried to ascertain what the intent might likely be to create this kind of extension. Picked apart:

  1. The property is for a closure that takes a closure argument, and returns an NSArray.
  2. In the implementation we are creating the getter for this closure as per the readonly property attribute.

Normally we would inject/set the block with the setter however to fulfill the contract we could just construct it as an instance variable "someMapped" as follows.

@implementation NSArray (Sample)

typedef NSArray *_Nonnull (^mapped)( id __nullable (^block)(id __nonnull) );

-(mapped)mapped {

   //Normally someMapped block definition would be injected/set by the setter -(void) setMapped:(mapped) aMapped {
   mapped someMapped = ^(id __nonnull someId) {
       NSMutableArray * new = [[NSMutableArray alloc] init];
       for( NSMutableDictionary* dict in self) {
           NSMutableString * str = [dict objectForKey:someId];
           [str stringByAppendingString:@".png"];
           [new addObject:str];
       }
     return [new copy];
    };

  return someMapped;
}

@end
bhartsb
  • 1,316
  • 14
  • 39

1 Answers1

0

It isn't clear what you are trying to do. Are you trying to implement a map type function on NSArray? If so, then there is no need for an @property, which would imply that you are storing something associated with they instance. You probably just want a method:

typedef id __nullable (^bt_MapBlockT)(id __nonnull);
- (NSArray *)bt_map:(bt_MapBlockT) block;
// written in browser... probably hosed the syntax slightly.

There are a slew of examples floating about that implement map-reduce-filter-whatever on NSArray, btw.

bbum
  • 162,346
  • 23
  • 271
  • 359
  • It is exactly as stated a property as per the @interface declaration. I had a question like this on a coding challenge so I'm trying to figure it out what it is trying to do too. But changing the intention is not the answer. – bhartsb Aug 11 '18 at 20:09
  • @bhartsb Then the question on the challenge is wrong. That happens. The correct answer is to change the intention because the intention is wrong. There is absolutely no reason to store the block and, thus, using an `@property` is incorrect. – bbum Aug 12 '18 at 00:59
  • @bhartsb Feel free to refer the author of the coding challenge to me. I'm happy to help them correct the challenge. – bbum Aug 12 '18 at 01:01
  • The block name map should be mapped, but I don't think that should make any difference. I'll PM you on LinkedIn. – bhartsb Aug 12 '18 at 07:56
  • The question said "implement the following category" and "pay special attention to the interface: this is the contract you need to meet". I modified my OP to show the alternate way that I think meets the contract, but doing this is unfamiliar to me. As in I'm not getting the point of it. – bhartsb Aug 12 '18 at 08:33
  • See the answers on this question. https://stackoverflow.com/questions/6127638/nsarray-equivalent-of-map. It has some example implementations of `map` like functionality. – bbum Aug 12 '18 at 16:50
  • As for the original question, you can split it into two. The second part is that you take the block and enumerate the array as per that linked question. The first part is that you have to store the block somewhere. Given that it is a category on `NSArray`, you can't use instance variables. So, you'd most likely use an `associated object`. Which is why the question is so badly worded; going way out on a limb to add storage for a block using a hackish mechanism when no storage is needed is misleadingly pointless for an academic exercise. – bbum Aug 12 '18 at 16:52
  • See what I added in the OP with "Technically I think the above would fulfill the extension's contract..." Does this make sense? Possibly the block/closure could be changed out in this way to provide different behaviors but this seems odd to me. – bhartsb Aug 12 '18 at 22:20
  • @bhartsb Yup; that looks like a map implementation to me! – bbum Aug 12 '18 at 23:16