progrium/darwinkit

Dictionary's DictionaryWithObjectsAndKeys() throws NSInvalidArgumentException

Opened this issue · 6 comments

Dictionary's DictionaryWithObjectsAndKeys() throws an NSInvalidArgumentException when it is used.

This example program will cause an exception to be thrown when ran:

// Description: use Dictionary's DictionaryWithObjectsAndKeys() method

package main

import "fmt"
import f "github.com/progrium/macdriver/macos/foundation"

func main() {
	key := f.String_StringWithString("key")
	value := f.String_StringWithString("value")
	dict := f.DictionaryClass.DictionaryWithObjectsAndKeys(value, key, nil)
	fmt.Println("dictionary:", dict.Description())
}

Here is the error message produced by running this program:

2024-01-16 11:27:55.399 erase[2602:43591] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSDictionary dictionaryWithObjectsAndKeys:]: second object of each pair must be non-nil.  Or, did you forget to nil-terminate your parameter list?'
*** First throw call stack:
(
	0   CoreFoundation                      0x000000019df12b08 __exceptionPreprocess + 240
	1   libobjc.A.dylib                     0x000000019dc5de14 objc_exception_throw + 60
	2   CoreFoundation                      0x000000019de7d968 +[NSDictionary dictionaryWithObjectsAndKeys:] + 800
	3   libffi.dylib                        0x00000001ac030050 ffi_call_SYSV + 80
	4   libffi.dylib                        0x00000001ac038ae8 ffi_call_int + 1208
	5   erase                               0x0000000104650c9c runtime.asmcgocall.abi0 + 124
)
libc++abi: terminating with uncaught exception of type NSException
SIGABRT: abort
PC=0x19dd90db8 m=0 sigcode=0
signal arrived during cgo execution

The program still crashes when nil is removed from DictionaryWithObjectsAndKeys() arguments.

This is an equivalent Objective-C program:

// Description: Demonstrate the use of NSDictionary's dictionaryWithObjectsAndKeys:
// Build command: clang -framework foundation dictionarytest.m && ./a.out

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                    @"value", @"key", nil];
        NSLog(@"%@", dictionary);
    }
    return 0;
}

When the nil argument is removed, the same kind of crash and message is displayed that the Go program experiences.

Strange, it should work with nil but maybe nil isn't being converted properly?

It looks like Objective-C doesn't like Go's nil.

Wanna look into that? Write some failing tests and then look into the conversion code to see if you can fix and make tests pass with a PR.

Actually I am finishing up my work now.

These are all the methods I know that are effected by the same issue - having to terminate a list of objects using nil:

NSDictionary initWithObjectsAndKeys
NSDictionary dictionaryWithObjectsAndKeys
NSMutableDictionary initWithObjectsAndKeys
NSMutableDictionary dictionaryWithObjectsAndKeys
NSArray arrayWithObjects
NSArray initWithObjects
NSArray NewArrayWithObjects
NSMutableArray arrayWithObjects
NSMutableArray initWithObjects
NSMutableArray NewMutableArrayWithObjects

If anyone knows of more, please let me know. Thank you.