我正在尝试使用Objective-C为在Mac上运行的应用程序创建Unity插件。我需要在使用url协议从链接启动我的应用程序时获取URL。我之前没有使用过Objective-C,所以我在尝试使它工作时遇到了麻烦。
我正在使用Unity提供的示例(download example)并将方法更改为我需要获取URL的方法,但我的应用程序在_GetUrl方法的行nsApplication = [[NSApplication alloc] init];
上崩溃了。我不知道我错过了什么/做错了什么。另外,当我想要求url(在第一帧调用)时,_GetUrl是从Unity调用的方法,但我担心它可能会在applicationWillFinishLaunching之后被调用。那么我应该在哪里设置委托,以便在设置委托后发生applicationWillFinishLaunching?
我使用.h和.m脚本然后编译捆绑包并将其作为插件导入Unity。这是我的代码:
#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
#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
答案 0 :(得分:0)
如果您的应用程序崩溃,您需要提供一些信息,例如堆栈跟踪或错误消息,以便我们提供最佳帮助。我假设你收到的错误是这样的:
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的插件引擎并不是特别熟悉,所以我不知道是否有特定的&#34;加载&#34;自动调用的函数(我不会在示例代码中看到一个)。你可能要自己打电话。它必须在插件加载后发生,但在Get URL Apple事件发生之前(它不清楚你希望生成什么)。
只是好奇你正在努力实现这一目标。我从来没有见过以这种方式使用的协议处理程序。
答案 1 :(得分:0)
创建NSApplication实例看起来非常可疑。通常你不会创建它,因为它是一个单身的定义。
所以不要这样:
if (nsApplication == nil)
nsApplication = [[NSApplication alloc] init];
你应该更喜欢这个(获取当前的NSApplication实例):
if (nsApplication == nil)
nsApplication = [NSApplication sharedApplication];
答案 2 :(得分:0)
我就此做了一个教程,请参阅Override app delegate in Unity for iOS and OSX (4/4) Inject code to Mach-O binary。
它使用代码注入来设置Objective-C类来响应相应的Apple Event。