簡體   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