Apple Metal без Interface Builder

Я ломаю голову над этим. Я пытался продублировать первоначальный металлический проект, предоставленный Apple, но вообще без использования конструктора интерфейсов. Я могу создать окно, но оно пустое, ничего не отображается, и я не могу понять, почему.

main.m

#import <Cocoa/Cocoa.h>
#import "AppDelegate.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSApplication* app = [NSApplication sharedApplication];
        AppDelegate* appDelegate = [[AppDelegate alloc] init];

        [app setDelegate:appDelegate];

        [app run];
    }

    return EXIT_SUCCESS;
}

AppDelegate.h

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate> {
    NSWindow *window;
}

@end

AppDelegate.m

#import <Metal/Metal.h>

#import "AppDelegate.h"

#import "GameViewController.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

- (id)init {
    if (self = [super init]) {
        NSScreen* mainScreen = [NSScreen mainScreen];

        NSRect frame = NSMakeRect(0, 0, mainScreen.frame.size.width / 2, mainScreen.frame.size.height / 2);

        NSUInteger styleMask =
            NSWindowStyleMaskTitled |
            NSWindowStyleMaskResizable |
            NSWindowStyleMaskClosable |
            NSWindowStyleMaskMiniaturizable;

        NSBackingStoreType backing = NSBackingStoreBuffered;


        window = [[NSWindow alloc] initWithContentRect:frame styleMask:styleMask backing:backing defer:YES];
        [window center];


        GameViewController* gvc = [[GameViewController alloc] init];

        MTKView* metalView = [[MTKView alloc] initWithFrame:frame device:MTLCreateSystemDefaultDevice()];

        [metalView setClearColor:MTLClearColorMake(0, 0, 0, 1)];
        [metalView setColorPixelFormat:MTLPixelFormatBGRA8Unorm];
        [metalView setDepthStencilPixelFormat:MTLPixelFormatDepth32Float];
        [metalView setDelegate:gvc];

        [gvc setView:metalView];

        [window setContentView:metalView];
        //[window setContentViewController: gvc];

    }
    return self;
}

- (void)applicationWillFinishLaunching:(NSNotification *)notification {
    [window makeKeyAndOrderFront:self];
}

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

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

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
    return YES;
}

@end

Остальные файлы; GameViewController.h, GameViewController.m, Shaders.metal, SharedStructures.h; такие же, как XCode 8.2.1 (8C1002) auto, генерируемые автоматически при создании игрового проекта, использующего Metal с Objective-c.

Вы заметите, что строка [window setContentViewController: gvc]; закомментирована. Когда это не прокомментировано, я получаю EXEC_BAD_ACCESS в первой строке GameViewController.m функции рендеринга dispatch_semaphore_wait(_inflight_semaphore, DISPATCH_TIME_FOREVER);

Ясно, что есть что-то, чего мне не хватает, но я гуглил весь день и, похоже, не могу этого понять. Любая помощь горячо приветствуется.


person Rojuinex    schedule 24.12.2016    source источник


Ответы (1)


Проблема в том, что когда NSViewController, такой как GameViewController, не загружается из NIB, он не вызывает метод -viewDidLoad. GameViewController выполняет важную работу в этом методе.

Вы можете переместить создание вида в переопределение -loadView в GameViewController. Создайте представление и назначьте его self.view. Вам не нужно устанавливать его делегата. Существующий GameViewController код уже делает это. Настройка свойств представления должна быть перемещена в -_setupView, где существующий код уже выполняет подобные вещи.

Не создавайте представление в -[AppDelegate init]. Очевидно, вы также не сможете установить там представление контроллера представления. Просто установите контроллер представления в качестве контроллера представления содержимого окна (раскомментируйте эту строку), а все остальное будет сделано автоматически. Когда окно запрашивает свойство view контроллера представления содержимого, оно вызывает ваше переопределение -loadView вместе с существующим -viewDidLoad и т. Д.

person Ken Thomases    schedule 25.12.2016