So I am working on a sort of GLFW-lite framework and am doing the cocoa part. I am trying to get the input working but it is not working. Basically, my view interface has a pointer to a struct with an array in it. I know for a fact that the array is initialized because in it's initialization function I print out some values from it. (Also, I initialized the array) But in the keyDown function, it gives me an exc_bad_access for some reason. I did my best to replicate the error in the least lines of code possible while still keeping the same program structure. (Also, don't give me a hard time about the structure of the replication, the library is designed in a cleaner way.)
#include <Cocoa/Cocoa.h>
#include <stdlib.h>
typedef struct _Window {
//For storing key states
int *keys;
} Window;
int numKeys = 5;
Window* createWindow() {
Window* window = malloc(sizeof(Window));
window->keys = malloc(sizeof(int) * numKeys);
memset(window->keys, 0, numKeys);
return window;
}
@interface View : NSView {
Window* win;
}
- (id) init:(Window*)window;
@end
@implementation View
- (id) init:(Window*)window {
win = window;
self = [[View alloc] initWithFrame: NSMakeRect(0, 0, 800, 600)];
return self;
}
- (BOOL)acceptsFirstResponder {
return YES;
}
- (void) keyDown:(NSEvent *)event {
win->keys[4] = 1;
}
@end
int main() {
[NSApplication sharedApplication];
NSWindow *window = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, 800, 600)
styleMask: NSWindowStyleMaskClosable
| NSWindowStyleMaskTitled
| NSWindowStyleMaskResizable
| NSWindowStyleMaskMiniaturizable
backing: NSBackingStoreBuffered
defer: NO];
[window center];
[window setTitle:@"Window Title"];
[window makeKeyAndOrderFront:nil];
[window orderFrontRegardless];
Window* keyStates = createWindow();
View* view = [[View alloc] init:keyStates];
[window setContentView:view];
[window makeFirstResponder:view];
[NSApp run];
}
If I try to access the window keys in the initialization function of the interface it works. So why does it give me the error?
Here's what happens:
In main()
:
View* view = [[View alloc] init:keyStates];
View
A is allocated and init:
is called.
In init:
win = window;
View
A's win
is window
.
self = [[View alloc] initWithFrame: NSMakeRect(0, 0, 800, 600)];
View
B is allocated and initWithFrame:
is called.
return self;
View
B is returned. View
B doesn't have a win
.
Solution: don't allocate another View
in init:
.
- (instancetype)init:(Window *)window {
if (self = [super initWithFrame:NSMakeRect(0, 0, 800, 600)] {
win = window;
}
return self;
}