如何调用在运行时获得的 Objective-C 块?

How to invoke an Objective-C block obtained at runtime?

我正在尝试编写 HKHealthStore 的模拟。在存根 executeQuery: 中,我需要调用传递给它的 HKSampleQuery 实例的 result handler block。该块是私有的,因此我需要在运行时获取它。这是我目前所拥有的:

- (void)executeQuery:(HKQuery *)query {
    NSAssert([query isKindOfClass:HKSampleQuery.class], @"Mock executeQuery: not implemented yet for other query types than HKSampleQuery");

    HKSampleQuery *sampleQuery = (HKSampleQuery *)query;
    NSMutableArray<HKObject *> *queryResults = [NSMutableArray new];
    for (HKObject *o in self.storedObjects) {
        if ([sampleQuery.predicate evaluateWithObject:o]) {
            [queryResults addObject:o];
        }
    }

    SEL selector = NSSelectorFromString(@"resultHandler");
    Method m = class_getInstanceMethod(HKSampleQuery.class, selector);
    IMP imp = method_getImplementation(m);
    typedef void(*resultHandler_t)(id, SEL, void(^)(HKQuery*, NSArray*, NSError*));
    resultHandler_t f = (resultHandler_t)imp;

    // here, I need to invoke the result handler block with sampleQuery, queryResults and nil as arguments
}

请注意,尽管 HKSampleQuery 的初始值设定项的参数名为 "resultsHandler"。

,但选择器名称为 "resultHandler"

有什么方法可以用适当的参数调用块吗?

你没有做你认为你在做的事。您正在获取方法 resultHandler 的实现(属性 resultHandler 的 getter 方法)。你要的块是属性resultHandler,也就是return值的运行使用 getter 方法。换句话说,您需要 运行 getter 并得到结果,而不是 getter 本身。

调用该方法并获取 return 值的最简单方法(因为在这种情况下 return 值是常规对象指针类型)将是

typedef void (^resultHandler_t)(HKSampleQuery *query, NSArray *results, NSError *error);
resultHandler_t f = [sampleQuery performSelector:@selector(resultHandler)];
f(sampleQuery, queryResults, nil);

或者,如果您在 HKSampleQuery 的虚拟类别中声明(但不实现)实例方法或 属性 resultHandler,则您可以访问 属性直接点赞resultHandler_t f = sampleQuery.resultHandler;