Я новичок в разработке Swift и Ma c и пытаюсь создать фреймворк (только macOS), который может открывать металлическое окно. Я использую Xcode версии 11.3.1 на macOS версии 10.15.2.
Я начал с примеров, которые нашел в Интернете (запуск проекта macOS / Command Line Tool), и я не вижу, как это исправить ошибка:
[CAMetalLayer nextDrawable], возвращающий ноль, потому что распределение не удалось.
Когда проект создается с раскадровкой (проект MacOS / App), открывается окно с ожидаемым содержимое (заполнение красным цветом), но когда я пытаюсь заменить раскадровку на код (проект macOS / Command Line Tool), выполнение повторяется из-за указанной выше ошибки.
Main.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.
}
}
}
Renderer.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
, но это не решило мою проблему .