繁体   English   中英

捆绑包中NSApplication委托的使用

[英]Use of NSApplication delegate in bundle

我正在尝试为在Mac上运行的应用程序使用Objective-C为Unity创建一个插件。 从使用url协议的链接启动应用程序时,我需要获取URL。 我以前没有使用过Objective-C,所以在尝试使其工作时遇到了麻烦。

我正在使用Unity提供的示例( 下载示例 ),并将方法更改为获取URL所需的方法,但是我的应用程序在nsApplication = [[NSApplication alloc] init];行崩溃nsApplication = [[NSApplication alloc] init]; 在_GetUrl方法上。 我不知道我在想什么/做错了什么。 另外,_GetUrl是我要询问url时从Unity调用的方法(在第一帧调用),但是我恐怕它可能在applicationWillFinishLaunching之后被调用。 那么我应该在哪里实际设置委托,以便在设置委托后发生applicationWillFinishLaunching?

我使用.h和.m脚本,然后编译捆绑软件并将其作为插件导入到Unity中。 这是我的代码:

PluginUrlHandler.h

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

@interface NSApplicationDelegate : NSObject
{
    NSString* urlString;
}

// NSApplication delegate methods
- (void)applicationWillFinishLaunching:(NSNotification *)aNotification;
- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;

//Other methods
- (NSString *)getUrl;
@end

PluginUrlHandler.m

#import <Foundation/Foundation.h>
#import "PluginUrlHandler.h"

@implementation NSApplicationDelegate

- (id)init
{
    self = [super init];
    urlString = @"nourl";
    return self;
}

- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
    NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
    [appleEventManager setEventHandler:self
                           andSelector:@selector(handleGetURLEvent:withReplyEvent:)
                         forEventClass:kInternetEventClass andEventID:kAEGetURL];

}

- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
    [event paramDescriptorForKeyword:keyDirectObject] ;

    NSString *urlStr = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];

    urlString = urlStr;
}

- (NSString *)getUrl
{
    return urlString;
}

@end

static NSApplicationDelegate* delegateObject = nil;
static NSApplication* nsApplication = nil;


// Helper method to create C string copy
char* MakeStringCopy (const char* string)
{
    if (string == NULL)
        return NULL;

    char* res = (char*)malloc(strlen(string) + 1);
    strcpy(res, string);
    return res;
}

#if c__plusplus
extern "C" {
#endif

    const char* _GetUrl ()
    {
        if (delegateObject == nil)
        delegateObject = [[NSApplicationDelegate alloc] init];

        if (nsApplication == nil)
            nsApplication = [[NSApplication alloc] init];

        [nsApplication setDelegate:delegateObject];

        return MakeStringCopy([[delegateObject getUrl] UTF8String]);
    }

#if c__plusplus
}
#endif

如果您的应用程序崩溃了,则需要提供一些信息,例如堆栈跟踪或错误消息,以便我们提供最佳帮助。 我假设您收到的错误如下所示:

2016-03-06 10:07:14.388 test[5831:230418] *** Assertion failure in -[NSApplication init], /Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1404.34/AppKit.subproj/NSApplication.m:1980
2016-03-06 10:07:14.391 test[5831:230418] An uncaught exception was raised
2016-03-06 10:07:14.391 test[5831:230418] Creating more than one Application

您不应该创建自己的NSApplication对象。 只需通过引用[NSApplication sharedApplication]使用系统。

通常来说,您不需要为插件安装NSApplication (或NSApplicationDelegate )。 加载的程序应该已经有一个,并且您不想弄乱它。 只需创建一个自定义NSObject子类作为您的AppleEvent处理程序即可。 您完全不需要NSApplication (或它的委托)。 任何对象都可以成为AppleEvent的目标。

在任何情况下,您都不能通过插件使用诸如applicationDidFinishLaunching:withOptions:类的东西。 太晚了。 该应用程序自启动以来已久。 您需要在从Unity调用的某些函数中添加AppleEvent处理程序。 我对Unity的插件引擎不是特别熟悉,所以我不知道是否有一个特定的“加载”函数会自动调用(示例代码中没有看到)。 您可能必须自己打个电话。 它必须在加载插件之后但在“获取URL Apple事件”发生之前发生(尚不清楚您期望生成什么)。

只是好奇您要尝试实现的目标。 我从未见过使用这种方式的协议处理程序。

创建NSApplication实例看起来非常可疑。 通常,您不会创建它,因为根据定义它是单例的。

所以代替这个:

if (nsApplication == nil)
   nsApplication = [[NSApplication alloc] init];

您应该这样做(获取当前的NSApplication实例):

if (nsApplication == nil)
   nsApplication = [NSApplication sharedApplication];

我对此做了一个教程,请参见在iOS和OSX的Unity中覆盖应用委托(4/4)将代码注入Mach-O二进制文件

它使用代码注入来设置一个Objective-C类来响应相应的Apple Event。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM