我想在我的环境中设置类似的东西。
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self
forKeyPath:[@"values." stringByAppendingString: @"MyPreference"]
options:NSKeyValueObservingOptionNew
context:NULL];
我是在Smalltalk环境中这样做的。特定的Smalltalk实际上可以通过objective-c运行时功能来驱动上述内容。问题是“自我”作为addObserver:
参数。从Smalltalk,我可以创建一个C函数指针,它将作为Smalltalk的回调函数。但它无法提供Object对ObjectiveC环境的概念。
所以我试图弄清楚如何使用适当的API从某种对象中蹦出来导致我创建的函数指针被执行。我查看了NSInvokation
和朋友,但没有一个用于包裹C函数指针。而且我不确定他们是否会翻译addObserver:forKeyPath:options:context:
来做正确的事。
归结为问题是,如何使用现有的Cocoa对象来注册对Notification的响应,该响应是执行C函数指针而不编译任何新的objc代码。
答案 0 :(得分:2)
您需要在Objective-C中创建一个胶水类。你可以这样做:
typedef void TravisGriggsCallback();
@interface TravisGriggsGlue {
TravisGriggsCallback *_callback;
}
- (id)initWithCallback:(TravisGriggsCallback *)callback;
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
@end
@implementation TravisGriggsGlue
- (id)initWithCallback:(TravisGriggsCallback *)callback
{
if (!(self = [super init]))
return nil;
_callback = callback;
return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
{
_callback();
}
@end
如果需要将参数传递给回调,则需要添加实例变量来保存参数,并将它们传递给init方法。
然后你就这样使用它:
TravisGriggsGlue *glue = [[TravisGriggsGlue alloc]
initWithCallback:&someCallbackFunction];
[[NSUserDefaultsController sharedUserDefaultsController]
addObserver:self
forKeyPath:[@"values." stringByAppendingString: @"MyPreference"]
options:NSKeyValueObservingOptionNew
context:NULL];
[glue release]; // only needed if not using ARC
答案 1 :(得分:1)
我不知道你使用的是哪种Smalltalk,但在pharo / squeak中你可能正在使用ObjectiveCBridge插件。如果是这种情况,您可以扩展ObjectiveCSqueakProxy并将其用作从cocoa委托给您的应用程序的对象。
希望这适合你:)
答案 2 :(得分:0)
使用简单的函数对象:
@interface MONFunctor : NSObject
- (void)performFunction;
@end
然后根据需要专门化:
@interface MONFunctorSpecialization : NSObject
{
@private
// data, state, arguments for function, function pointer...
}
- (void)performFunction;
@end
你可以使用仿函数作为监听器,但我勾勒出这个,好像你的监听器只会在回调中说[functor performFunction];
。
回想起来,MONFunctor
不需要成为一个班级;一个协议就足够了。