方法作为参数类型

Method as a parameter type

本文关键字:类型 参数 方法      更新时间:2023-09-26
我过去尝试从Objective-C

学习JavaScript,我很好奇在Objective-C中是否有可能有一个具有参数类型的方法。下面是 findIndex() JavaStript 函数的示例,该函数返回数组中通过测试的第一个元素的索引(作为函数提供)。如果可能的话,Objective-C的块实现会是什么样子?

如果我在 NSArray 上编写一个类类别,我将如何将一个块传递给一个方法并在它本身 (NSArray) 上执行该条件。如果不可能,我很想知道为什么。

    var ages = [3, 10, 18, 20];
    function checkAdult(age) {
        return age >= 18;
    }
    function myFunction() {
        document.getElementById("demo").innerHTML = ages.findIndex(checkAdult);
    }

这是我在另一个StackOverFlow问题中找到的一个有用的花絮,可能有助于块语法。我正在尝试实现的findIndex()函数的定义。

块语法

  1. 块作为方法参数模板

    - (void)aMethodWithBlock:(returnType (^)(parameters))blockName {
            // your code
    }
    

    -(void) saveWithCompletionBlock: (void (^)(NSArray *elements, NSError *error))completionBlock{
            // your code
    }
    
  2. 块作为方法参数模板

    [anObject aMethodWithBlock: ^returnType (parameters) {
        // your code
    }];
    

    [self saveWithCompletionBlock:^(NSArray *array, NSError *error) {
        // your code
    }];
    
  3. 块作为局部变量**模板

    returnType (^blockName)(parameters) = ^returnType(parameters) {
        // your code
    };
    

    void (^completionBlock) (NSArray *array, NSError *error) = ^void(NSArray *array, NSError *error){
        // your code
    };
    
  4. 阻止作为类型定义模板

    typedef returnType (^typeName)(parameters);
    typeName blockName = ^(parameters) {
        // your code
    } 
    


FindIndex()定义

Array.prototype.findIndex ( predicate [ , thisArg ] )

注意谓词应该是一个接受三个参数和 返回一个可强制转换为布尔值 true 或 false 的值。 findIndex 为数组的每个元素调用一次谓词,在 升序,直到找到谓词返回 true 的顺序。如果 找到这样的元素,findIndex 立即返回 该元素值。否则,findIndex 返回 -1。

Objective-C 中的相应代码:

@implementation NSArray (MyExtension)
- (NSUInteger)findIndexWithPredicate:(BOOL (^)(id element, NSUInteger index, NSArray* array))predicate {
    NSUInteger result = NSNotFound;
    if (NULL != predicate) {
        for (NSUInteger i = 0; i < self.count; i++) {
            if (predicate(self[i], i, self)) {
                result = i;
                break;
            }
        }
    }
    return result;
}
@end

请注意,我已将默认返回值从 -1 更改为 NSNotFound,因为索引是无符号的。

方法调用:

NSUInteger index = [@[@3, @10, @18, @20] findIndexWithPredicate:^BOOL(id element, NSUInteger index, NSArray *array) {
    return [element integerValue] >= 18;
}];

您可以避免在 JavaScript 第一个索引中定义的额外参数:

@implementation NSArray (MyExtension)
- (NSUInteger)findIndexWithPredicate:(BOOL (^)(id element))predicate {
    NSUInteger result = NSNotFound;
    if (NULL != predicate) {
        for (NSUInteger i = 0; i < self.count; i++) {
            if (predicate(self[i])) {
                result = i;
                break;
            }
        }
    }
    return result;
}
@end
NSUInteger index = [@[@3, @10, @18, @20] findIndexWithPredicate:^BOOL(id element) {
    return [element integerValue] >= 18;
}];

您可以使用enumerateObjectsUsingBlock:方法在不编写自定义类别的情况下获得相同的结果:

[@[@3, @10, @18, @20] enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    if ([obj integerValue] >= 18) {
        *stop = YES;
        index = idx;
    }
}];

此外,还可以使用块的替代方法,例如 C 函数指针。但是块提供了更大的灵活性。

我确实为鲍里斯制定了类似的解决方案:

NSArray *ages = @[@"3", @"10", @"18", @"20"];
BOOL(^parameter)(NSInteger integer) = ^BOOL(NSInteger integer) {
    if (integer >= 18) {
        return YES;
    }
    return NO;
};
NSInteger(^block)(BOOL(^parameter)(), NSArray *array) = ^NSInteger(BOOL(^parameter)(), NSArray *array) {
    for (NSUInteger i = 0; i < array.count; i++) {
        NSInteger arrayInteger = [array[i] intValue];
        if (parameter(arrayInteger) == YES) {
            return i;
        }
    }
    return -1;
};
NSInteger result = block(parameter, ages);