没有界面生成器的Apple Metal [英] Apple Metal without Interface Builder

查看:85
本文介绍了没有界面生成器的Apple Metal的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为此绞尽脑汁.我一直在尝试复制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];[应用程式执行];}返回退出成功;} 

AppDelegate.h

  #import< Cocoa/Cocoa.h>@interface AppDelegate:NSObject< NSApplicationDelegate>{NSWindow *窗口;}@结尾 

AppDelegate.m

  #import< Metal/Metal.h>#import"AppDelegate.h"#import"GameViewController.h"@interface AppDelegate()@结尾@implementation AppDelegate-(id)init {如果(自我= [超级初始化]){NSScreen * mainScreen = [NSScreen mainScreen];NSRect框架= 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];[窗口中心];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];}回归自我}-(void)applicationWillFinishLaunching:(NSNotification *)notification {[window makeKeyAndOrderFront:self];}-(void)applicationDidFinishLaunching:(NSNotification *)aNotification {//在此处插入代码以初始化您的应用程序}-(void)applicationWillTerminate:(NSNotification *)aNotification {//在此处插入代码以拆除您的应用程序}-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {返回是;}@结尾 

其他文件; GameViewController.h GameViewController.m Shaders.metal SharedStructures.h ;与创建使用Metal-Objective-c的游戏项目时XCode 8.2.1(8C1002)自动生成的内容相同.

您会注意到 [window setContentViewController:gvc]; 行已被注释掉.取消注释时,我在 GameViewController.m 的呈现函数 dispatch_semaphore_wait(_inflight_semaphore,DISPATCH_TIME_FOREVER)的第一行上得到一个 EXEC_BAD_ACCESS

很明显,我缺少一些东西,但是我整天都在搜索,所以我似乎无法弄清楚.非常感谢您的帮助.

解决方案

问题是,当未从NIB加载 NSViewController (例如 GameViewController )时,它不会调用 -viewDidLoad 方法. GameViewController 在该方法中起着重要的作用.

您可以将视图的创建移到 GameViewController 中的 -loadView 的替代中.创建视图并将其分配给 self.view .您无需设置其委托.现有的 GameViewController 代码已经做到了.设置视图的属性应该移到 -_ setupView 上,现有代码已经在执行这种操作了.

不要在-[AppDelegate init] 中创建视图.显然,您也将无法在该处设置视图控制器的视图.只需将视图控制器设置为窗口的内容视图控制器(取消注释该行),其余的将自动处理.当窗口请求内容视图控制器的 view 属性时,它将调用您对 -loadView 的覆盖以及现有的 -viewDidLoad 等.

I am racking my brain on this one. I've been trying to duplicate the initial metal project provided by Apple but without using interface builder at all. I'm able to create a window, but it's blank, nothing is rendering and I can't figure out why.

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

The other files; GameViewController.h, GameViewController.m, Shaders.metal, SharedStructures.h; are the same as what XCode 8.2.1 (8C1002) auto generates when you create a Game project that uses Metal with Objective-c.

You'll notice the line [window setContentViewController: gvc]; is commented out. When this is uncommented I get an EXEC_BAD_ACCESS on the first line of GameViewController.m's render function dispatch_semaphore_wait(_inflight_semaphore, DISPATCH_TIME_FOREVER);

Clearly there's something that I'm missing, but I've been googling all day and I can't seem to figure it out. Any help is much appreciated.

解决方案

The issue is that, when an NSViewController such as the GameViewController is not loaded from a NIB, it doesn't call the -viewDidLoad method. The GameViewController does important work in that method.

You can move the creation of the view into an override of -loadView in GameViewController. Create the view and assign it to self.view. You don't need to set its delegate. The existing GameViewController code does that already. Setting the view's properties should be moved to -_setupView where the existing code already does that sort of thing.

Don't create the view in -[AppDelegate init]. Obviously, you also won't be able to set the view controller's view there, either. Just set the view controller as the window's content view controller (uncomment that line) and the rest will be taken care of automatically. When the window requests the content view controller's view property, it will call your override of -loadView along with the existing -viewDidLoad, etc.

这篇关于没有界面生成器的Apple Metal的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆