我们正在做一个Qt项目,有一些Mac特定的代码需要添加。我们需要注册一个事件,在一个示例程序中,我们通过使用:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(notificationHandler:)
name:NSWorkspaceDidDeactivateApplicationNotification
object:nil];由于我们可以在Qt上的mm文件中直接使用它,因此我们采取的方法如下:
MyClass::MyClass() : {
// do other setup ...
CFNotificationCenterAddObserver
(
CFNotificationCenterGetLocalCenter(),
this,
¬ificationHandler,
CFSTR("???"),
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately
);
}"NSWorkspaceDidDeactivateApplicationNotification"??的字符串是什么或者我们如何将自己附加到这个特定的通知中?
我们尝试了NSGod的方法,但是因为没有Objective-C代码可以添加到带有Qt的.h中,所以我们添加了一个私有成员,它的类是在mm文件中定义的,它包含实际的逻辑。如下所示:
SelectedStuffManager.h
class MacWrap;
class SelectedStuffManager
{
public:
....
doSomething();
MacWrap* d;
private:
....
};SelectedStuffManager.mm
@class MDWorkspaceWatcher;
class MacWrap
{
public:
MacWrap();
~MacWrap();
void applicationDeactivated(NSNotification * notification);
SystemEventsApplication *systemApplication;
NSRunningApplication *runApp;
private:
MDWorkspaceWatcher *workspaceWatcher;
};
MacWrap::MacWrap() {
this->workspaceWatcher = [[MDWorkspaceWatcher alloc] initWithMyClass:this];
}
MacWrap::~MacWrap() {
[this->workspaceWatcher release];
}
void MacWrap::applicationDeactivated(NSNotification* notification)
{
// guardar el id del proceso para utilizarlo luego
runApp = [[notification userInfo] valueForKey:@"NSWorkspaceApplicationKey"];
NSString *systemEventsASppName = [runApp bundleIdentifier];
if( [ systemEventsASppName isNotEqualTo:@"com.yo.SelectedText"])
{
systemApplication = [SBApplication applicationWithBundleIdentifier:systemEventsASppName];
NSLog(@"Launched. %@",systemEventsASppName);
}
}
@interface MDWorkspaceWatcher : NSObject {
MacWrap *manager;
}
- (id)initWithMyClass:(MacWrap*)obj;
- (void)didDeactivateApp:(NSNotification *)notification; @end
@implementation MDWorkspaceWatcher
- (id)initWithMyClass:(MacWrap*)obj {
if ((self = [super init])) {
manager = obj;
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
selector:@selector(didDeactivateApp:)
name:NSWorkspaceDidDeactivateApplicationNotification
object:nil];
}
return self;
}
- (void)dealloc {
[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
[super dealloc];
}
- (void)didDeactivateApp:(NSNotification *)notification {
manager->applicationDeactivated(notification);
}
@end
SelectedStuffManager::SelectedStuffManager()
{
d = new MacWrap();
}
SelectedStuffManager::doSomething()
{
if ([[d->runApp localizedName] isEqualTo: @"something"]) --> here it fails, bad memory access
{
...
}
}似乎有人同时释放了runApp和systemApplication,所以我们得到了一个空指针或坏内存。这是如何或为什么会发生的?
发布于 2012-02-01 01:32:48
我不相信你能随心所欲地去做。首先,NSWorkspace使用自己的NSNotificationCenter,这与+defaultCenter返回的默认NSNotificationCenter不同。
我不相信有一个严格的CF-等同于那些NSWorkspace调用。可能存在高级别的基于碳的等价物,但它们在64位中不可用,因此应该避免使用。
您应该能够使用一个小的Objective-C helper类接收通知并将它们转发到C++类,如以下代码所示:
编辑:已更新以从头文件中删除任何Objective-C。只需使用可以在.mm文件中转换的通用void *指针即可。
.h:
//@class MDWorkspaceWatcher;
class MyClass {
private:
// MDWorkspaceWatcher *workspaceWatcher;
void *workspaceWatcher;
public:
MyClass();
~MyClass();
// const void didActivateApp(NSNotification *notification) const;
// const void didDeactivateApp(NSNotification *notification) const;
const void didActivateApp(void *anNSnotification) const;
const void didDeactivateApp(void *anNSnotification) const;
};.mm:
Objective-C部分:
@interface MDWorkspaceWatcher : NSObject {
MyClass *myClass;
}
- (id)initWithMyClass:(MyClass *)aMyClass;
@end
@implementation MDWorkspaceWatcher
- (id)initWithMyClass:(MyClass *)aMyClass {
if ((self = [super init])) {
myClass = aMyClass;
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
selector:@selector(didActivateApp:)
name:NSWorkspaceDidActivateApplicationNotification
object:nil];
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
selector:@selector(didDeactivateApp:)
name:NSWorkspaceDidDeactivateApplicationNotification
object:nil];
}
return self;
}
// very important:
- (void)dealloc {
[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
[super dealloc];
}
- (void)didActivateApp:(NSNotification *)notification {
myClass->didActivateApp(notification);
}
- (void)didDeactivateApp:(NSNotification *)notification {
myClass->didDeactivateApp(notification);
}
@endC++部件:
MyClass::MyClass() {
this->workspaceWatcher = [[MDWorkspaceWatcher alloc] initWithMyClass:this];
}
MyClass::~MyClass() {
[(MDWorkspaceWatcher *)this->workspaceWatcher release];
}
MyClass::didActivateApp(void *anNSnotification) {
NSDictionary *appInfo = [(NSNotification *)anNSnotification userInfo];
NSLog(@"appInfo == %@", appInfo);
}
MyClass::didDeactivateApp(void *anNSnotification) {
NSDictionary *appInfo = [(NSNotification *)anNSnotification userInfo];
NSLog(@"appInfo == %@", appInfo);
}注意,NSDictionary是用CFDictionaryRef免费桥接的,所以如果您更喜欢C而不是Objective-C,那么您可以简单地将appInfo NSDictionary转换为CFDictionaryRef,然后调用CF函数来获取字典的内容。
请注意,通知中心拥有appInfo字典(换句话说,它将自动发布),因此您不应该像使用CFCreate*/CFCopy*-related代码那样对它调用CFRelease()。
https://stackoverflow.com/questions/9080619
复制相似问题