【发布时间】:2020-06-29 10:40:24
【问题描述】:
我是 Swift 和 Mac 开发的新手,我正在尝试制作一个可以打开 Metal 窗口的框架(仅限 macOS)。我在 macOS 版本 10.15.2 上使用 Xcode 版本 11.3.1。
我从网上找到的示例开始(macOS/命令行工具项目开始),但我不知道如何纠正这个错误:
[CAMetalLayer nextDrawable] 因为分配失败而返回 nil。
当使用情节提要(macOS/App 项目)创建项目时,窗口会打开并显示预期的内容(填充为红色),但是当我尝试用代码(macOS/命令行工具项目)替换情节提要时,执行循环关于上面提到的错误。
主.swift
import AppKit
class AppDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow!
var viewController: ViewController!
func applicationDidFinishLaunching(_ notification: Notification) {
NSLog("Start app")
viewController = ViewController()
window = NSWindow(contentRect: NSMakeRect(0, 0, 1024, 768),
styleMask: .borderless,
backing: .buffered,
defer: false)
window.contentViewController = viewController
window.title = "Hey, new Window!"
window.backgroundColor = NSColor.blue
window.orderFrontRegardless()
}
func applicationWillTerminate(_ notification: Notification) {
NSLog("Terminate app")
}
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}
}
let app = NSApplication.shared
let appDelegate = AppDelegate()
app.delegate = appDelegate
app.run()
ViewController.swift
import Cocoa
import Metal
import MetalKit
class ViewController: NSViewController {
var mtkView: MTKView!
var renderer: Renderer!
override func loadView() {
mtkView = MTKView()
self.view = mtkView
}
override func viewDidLoad() {
super.viewDidLoad()
guard let defaultDevice = MTLCreateSystemDefaultDevice() else {
print("Metal is not supported on this device")
return
}
print("My GPU is: \(defaultDevice)")
mtkView.device = defaultDevice
guard let tempRenderer = Renderer(mtkView: mtkView) else {
print("Renderer failed to initialize")
return
}
renderer = tempRenderer
mtkView.delegate = renderer
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
渲染器.swift
import Foundation
import Metal
import MetalKit
class Renderer : NSObject, MTKViewDelegate {
let device: MTLDevice
let commandQueue: MTLCommandQueue
init?(mtkView: MTKView) {
device = mtkView.device!
commandQueue = device.makeCommandQueue()!
}
func draw(in view: MTKView) {
guard let commandBuffer = commandQueue.makeCommandBuffer() else { return }
guard let renderPassDescriptor = view.currentRenderPassDescriptor else { return }
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(1, 0, 0, 1)
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) else { return }
renderEncoder.endEncoding()
commandBuffer.present(view.currentDrawable!)
commandBuffer.commit()
}
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
}
}
在我的研究中,我发现只有一篇使用 NSViewControllerRepresentable 的帖子可以帮助我,但这并没有解决我的问题。
【问题讨论】:
-
我绝对不会尝试将一个命令行工具与生命周期应用程序融合在一起。
-
我同意马特的观点。
MTKView很可能需要成为窗口/视图层次结构的一部分才能正确分配缓冲区。 -
所以如果我理解正确的话,不可能在框架中定义允许您打开Metal窗口并控制其内容的条目?
-
您向我们展示的不是一个框架。它是一个命令行工具。它有一个 Main.swift。你说的是
app.run。这些都不会在框架中发生。 -
如果您收到的答复解决了您的问题,请采纳。
标签: swift macos storyboard runtime-error metal