如何调用在运行时获得的 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;
我正在尝试编写 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
的 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;