Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang + cgo - AppDelegate implementation doesn't work

I want to code an app in go that is able to open a custom filetype (.slc) on MacOS. I created a blank xcode project to get all the necessary code and implemented it via cgo into my app. When I double click a file the app opens but complains that it cannot open files in this format:

enter image description here

This is my Info.plist:

enter image description here

Implementation as follows:

/surge/appDelegate_darwin.go

package surge

//#cgo CFLAGS: -x objective-c
//#cgo LDFLAGS: -framework Cocoa
//#include "appDelegate_darwin.h"
import "C"

/surge/appDelegate_darwin.h

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate>


@end

/surge/appDelegate_darwin.m

#include "appDelegate_darwin.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

-(BOOL)application:(NSApplication *)sender openFile:(NSString *)filename
{
   NSLog(@"%@", filename);
   YES;
}
 
-(void)application:(NSApplication *)sender openFiles:(NSArray *)filenames
{
   NSLog(@"%@", filenames);
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application
}

- (void)applicationWillTerminate:(NSNotification *)aNotification {
    // Insert code here to tear down your application
}

@end

Additional information: I use the wails framework (https://wails.app) to add a nice vue.js frontend to the app and use the built-in wails build command.

Other implementations in cgo and objective-c (like custom protocol handler) work.

like image 800
Crack_David Avatar asked Aug 14 '20 09:08

Crack_David


1 Answers

After some sleepless nights I found my own solution through investigating and learning how a regular mac app is structured.

Additionally to implementing AppDelegate it is also necessary to implement Document and some additional functions to get it running. Here is my

/surge/appDelegate_darwin.h

#import <Cocoa/Cocoa.h>

extern void HandleFile(char *);

@interface AppDelegate : NSObject <NSApplicationDelegate>

@end

@interface Document : NSDocument

@end

/surge/appDelegate_darwin.m

#include "appDelegate_darwin.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

-(BOOL)application:(NSApplication *)sender openFile:(NSString *)filename
{
   YES;
}
 
-(void)application:(NSApplication *)sender openFiles:(NSArray *)filenames
{
   NSLog(@"%@", filenames);
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application
}


- (void)applicationWillTerminate:(NSNotification *)aNotification {
    // Insert code here to tear down your application
}


@end

@interface Document ()

@end

@implementation Document

- (instancetype)init {
    self = [super init];
    if (self) {
        // Add your subclass-specific initialization here.
    }
    return self;
}

+ (BOOL)autosavesInPlace {
    return YES;
}


- (NSString *)windowNibName {
    // Override returning the nib file name of the document
    // If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
    return @"Document";
}


- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {
    // Insert code here to write your document to data of the specified type. If outError != NULL, ensure that you create and set an appropriate error if you return nil.
    // Alternatively, you could remove this method and override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
    [NSException raise:@"UnimplementedMethod" format:@"%@ is unimplemented", NSStringFromSelector(_cmd)];
    return nil;
}


- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError {
    NSData *dataFromFile = [data retain];
    NSString *myString = [[NSString alloc] initWithData:dataFromFile encoding:NSUTF8StringEncoding];

    // This is the place where the magic happens. In my case I just call the HandleFile-function to process the file contents in my main go app
    NSLog(@"Data received: %@", myString);
    HandleFile([myString UTF8String]);
    return YES;
}


@end

I hope someone finds this useful!

like image 108
Crack_David Avatar answered Nov 05 '22 02:11

Crack_David