没有 Interface Builder 的 Apple Metal
Apple Metal without Interface Builder
我正在为这个绞尽脑汁。我一直在尝试复制 Apple 提供的初始金属项目,但根本没有使用界面生成器。我可以创建一个 window,但它是空白的,没有任何渲染,我不明白为什么。
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) 在您创建一个使用 Metal with Objective-c.
的游戏项目时自动生成的内容相同
您会注意到 [window setContentViewController: gvc];
行被注释掉了。当取消注释时,我在 GameViewController.m
的渲染函数 dispatch_semaphore_wait(_inflight_semaphore, DISPATCH_TIME_FOREVER);
的第一行得到一个 EXEC_BAD_ACCESS
显然我遗漏了一些东西,但我整天都在谷歌搜索,但我似乎无法弄清楚。非常感谢任何帮助。
问题是,当 NSViewController
(例如 GameViewController
)不是从 NIB 加载时,它不会调用 -viewDidLoad
方法。 GameViewController
在该方法中做了重要的工作。
您可以将视图的创建移动到覆盖 GameViewController
中的 -loadView
中。创建视图并将其分配给 self.view
。您不需要设置它的委托。现有的 GameViewController
代码已经这样做了。设置视图的属性应该移至 -_setupView
,现有代码已经在其中执行此类操作。
不要在 -[AppDelegate init]
中创建视图。显然,您也不能在那里设置视图控制器的视图。只需将视图控制器设置为 window 的内容视图控制器(取消注释该行),其余的将自动处理。当 window 请求内容视图控制器的 view
属性 时,它将调用您对 -loadView
的覆盖以及现有的 -viewDidLoad
等
我正在为这个绞尽脑汁。我一直在尝试复制 Apple 提供的初始金属项目,但根本没有使用界面生成器。我可以创建一个 window,但它是空白的,没有任何渲染,我不明白为什么。
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) 在您创建一个使用 Metal with Objective-c.
您会注意到 [window setContentViewController: gvc];
行被注释掉了。当取消注释时,我在 GameViewController.m
的渲染函数 dispatch_semaphore_wait(_inflight_semaphore, DISPATCH_TIME_FOREVER);
EXEC_BAD_ACCESS
显然我遗漏了一些东西,但我整天都在谷歌搜索,但我似乎无法弄清楚。非常感谢任何帮助。
问题是,当 NSViewController
(例如 GameViewController
)不是从 NIB 加载时,它不会调用 -viewDidLoad
方法。 GameViewController
在该方法中做了重要的工作。
您可以将视图的创建移动到覆盖 GameViewController
中的 -loadView
中。创建视图并将其分配给 self.view
。您不需要设置它的委托。现有的 GameViewController
代码已经这样做了。设置视图的属性应该移至 -_setupView
,现有代码已经在其中执行此类操作。
不要在 -[AppDelegate init]
中创建视图。显然,您也不能在那里设置视图控制器的视图。只需将视图控制器设置为 window 的内容视图控制器(取消注释该行),其余的将自动处理。当 window 请求内容视图控制器的 view
属性 时,它将调用您对 -loadView
的覆盖以及现有的 -viewDidLoad
等