我一直想知道以下情况是否可行:
给定函数foo
定义为
- (void)foo:(int)n action:(SEL)selector
{
// do something, maybe fetching data from server
...
// at a later point
[self performSelector:@selector(selector) withObject:returnObject];
}
注意:foo
是一个发给您的黑盒子功能。它无论如何都无法改变
通常会创建函数bar
- (id)bar:(id)x
{
return x;
}
并致电[self foo:n action:@selector(bar:)]
以获得函数bar
;
相反,我想知道是否可以包装该函数并使其同步,以便我只需要调用
- (id)foobar:(int)n;
获取通常由bar
答案 0 :(得分:1)
一种方法是使用no-op选择器调用foo:action:
,该选择器保存在实例变量中传递给它的任何对象,然后手动调用bar:
:
- (void)saveAsIvar:(id)var
{
_returnObject = var;
[_fooLock unlock];
}
- (id)bar:(id)x { return whatever; }
- (id)foobar:(int)n
{
[_fooLock lock];
[self foo:n action:@selector(saveAsIvar:)]
while (YES) {
if ([_fooLock tryLock]) {
return [self bar:_returnObject];
}
}
}
答案 1 :(得分:1)
你正在努力的是foo是有缺陷的。它不应该掉落bar的结果。 foo调用(bar)的选择器应该执行完成代码。
如果你想用foo编写这个工作,你将不得不做一些相当严重的黑客攻击和削减。
我会:
让foo在完成后发布通知,并将结果放入通知的用户词典中。
让foobar完成一个块。让它注册一个通知监听器,它将结果值从通知的用户信息字典中取出并传递给完成块。
答案 2 :(得分:0)
如果我理解正确,您正在尝试创建动态函数名称。所以例如我有一个方法 - (void)fizz:(id)x然后我会调用 - (id)foofizz:(int)n
虽然我没有尝试过,但听起来不是一个好主意,但可以通过使用消息转发来实现 https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html
答案 3 :(得分:0)
在目标c中实现这一点的通常方法是使用块,这些块基本上是像函数指针一样传递的代码块。您将添加一个块作为foo方法的参数。当foo完成其工作时,它应该调用传递给它的块,允许任何客户端在完成foo时执行工作。
在你的.h:
- (void)foo:(int)n withCompletion:(void (^)(id fooResult))completion;
在你的.m
- (void)foo:(int)n withCompletion:(void (^)(id fooResult))completion {
//do foo stuff
//invoke the completion block with the result of foo
if (completion) {
completion(someResult);
}
}
现在在你的客户端类中(即,谁试图使用foo)。像这样打电话给foo:
[someObject foo:someInt withCompletion:^(id fooResult) {
[self bar:fooResult];
}];
这里客户端调用foo并指定在完成时要做什么,在这种情况下,调用bar的结果为foo。
以下是Apple docs,您可以在其中了解有关Objective-C块的更多信息。