如何从Cocoa Notification蹦床到调用c函数指针?

Tra*_*ggs 5 cocoa smalltalk objective-c

我想在我的环境中设置这样的东西.

[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self
    forKeyPath:[@"values." stringByAppendingString: @"MyPreference"]
    options:NSKeyValueObservingOptionNew
    context:NULL];
Run Code Online (Sandbox Code Playgroud)

我是在Smalltalk环境中这样做的.特定的Smalltalk实际上可以通过objective-c运行时功能来驱动上述内容.问题在于那里的"自我"作为addObserver:论点.从Smalltalk,我可以创建一个C函数指针,它将作为Smalltalk的回调函数.但它无法提供Object对ObjectiveC环境的概念.

所以我试图弄清楚如何使用适当的API从某种对象中蹦床,导致我创建的函数指针被执行.我看过NSInvokation和朋友们,但没有一个用来包裹C函数指针.而且我不确定他们会翻译addObserver:forKeyPath:options:context:做正确的事情.

简而言之,问题是,如何使用现有的Cocoa对象来注册对Notification的响应,该响应是执行C函数指针而不编译任何新的objc代码.

rob*_*off 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
Run Code Online (Sandbox Code Playgroud)

如果需要将参数传递给回调,则需要添加实例变量来保存参数,并将它们传递给 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
Run Code Online (Sandbox Code Playgroud)